PowerShell Switch Statement (With Examples)

The PowerShell switch statement compares a value against a list of conditions and runs the script block of every condition that matches. It’s a cleaner replacement for a long chain of if/elseif statements.

Here’s the basic form, with a default block for anything that doesn’t match:

$state = 'TX'

switch ($state) {
    'CA'    { 'California' }
    'TX'    { 'Texas' }
    'WA'    { 'Washington' }
    default { 'Unknown state' }
}

Output:

Texas

In this guide, I’ll cover multiple conditions, greater than and less than checks, wildcards, regex, case sensitivity and arrays. I’ll also show the difference between break and continue, which trips up almost everyone.

I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, and the switch statement behaves the same in both.

Store the result of a switch in a variable

A switch statement outputs whatever its script blocks output, so you can assign it directly:

$code = 404

$message = switch ($code) {
    200     { 'OK' }
    404     { 'Not Found' }
    500     { 'Server Error' }
    default { "Unexpected status $code" }
}

"Status ${code}: $message"

Output:

Status 404: Not Found

For just two or three branches, if-else statements can be simpler.

Why does PowerShell switch run more than one case?

PowerShell doesn’t stop at the first match. It checks every condition and runs each one that matches:

$score = 92

switch ($score) {
    { $_ -ge 90 } { 'Grade A' }
    { $_ -ge 80 } { 'Grade B' }
    { $_ -ge 70 } { 'Grade C' }
}

Output:

Grade A
Grade B
Grade C
PowerShell switch statement running every matching case
All three conditions match, so all three blocks run

Add break to stop after the first match. This is the pattern you want for ranges like grades:

$score = 92

switch ($score) {
    { $_ -ge 90 } { 'Grade A'; break }
    { $_ -ge 80 } { 'Grade B'; break }
    { $_ -ge 70 } { 'Grade C'; break }
    default       { 'Grade F' }
}

Output:

Grade A

Switch with greater than and less than conditions

A condition can be a script block. PowerShell runs it with the current value in $_ and treats a $true result as a match:

$ages = 12, 25, 47, 70

foreach ($age in $ages) {
    $group = switch ($age) {
        { $_ -lt 18 }                 { 'Minor'; break }
        { $_ -ge 18 -and $_ -lt 35 }  { 'Young adult'; break }
        { $_ -ge 35 -and $_ -lt 65 }  { 'Adult'; break }
        default                       { 'Senior' }
    }
    "$age -> $group"
}

Output:

12 -> Minor
25 -> Young adult
47 -> Adult
70 -> Senior
PowerShell switch statement with greater than and less than conditions
Script block conditions in PowerShell 7

Because each range has break, an age matches only one group even if later conditions would also be true.

Switch with multiple conditions for one action

To run the same code for several values, use -in inside a script block condition:

$day = 'Saturday'

switch ($day) {
    { $_ -in 'Saturday', 'Sunday' } { 'Weekend'; break }
    { $_ -in 'Monday', 'Friday' }   { 'Long meeting day'; break }
    default                         { 'Regular workday' }
}

Output:

Weekend

You might expect to write the values as a comma-separated list. That’s a syntax error in PowerShell:

switch ('b') {
    'a', 'b' { 'Matched a or b' }
}

Output:

ParserError: C:\psfaqs\comma.ps1:2
Line |
   2 |      'a', 'b' { 'Matched a or b' }
     |         ~
     | Missing statement block in switch statement clause.

A regex alternation such as switch -Regex ($day) { '^(Saturday|Sunday)$' { 'Weekend' } } also works if you prefer patterns.

Use wildcards in a switch statement

Add -Wildcard to match with * and ?, just like the -like operator:

$files = 'report-2026.xlsx', 'backup.ps1', 'notes.txt', 'Q3-report.pdf'

foreach ($file in $files) {
    switch -Wildcard ($file) {
        '*.ps1'    { "$file is a script" }
        '*report*' { "$file is a report" }
        '*.txt'    { "$file is plain text" }
    }
}

Output:

report-2026.xlsx is a report
backup.ps1 is a script
notes.txt is plain text
Q3-report.pdf is a report

Each file matched one pattern here. A name like report.txt would match two patterns, and both blocks would run.

Some articles suggest putting an array of patterns in one condition. It doesn’t work, because PowerShell doesn’t compare against each element:

switch -Wildcard ('banana') {
    @('apple', 'banana') { 'Matched the array' }
    default              { 'No match' }
}

Output:

No match

Check if a string contains text

For a “contains” check, wrap the text in * wildcards. Wildcard matching is case-insensitive too:

$subject = 'URGENT: Server SRV01 is down'

switch -Wildcard ($subject) {
    '*urgent*' { 'Flag as high priority' }
    '*down*'   { 'Open an incident' }
}

Output:

Flag as high priority
Open an incident

Use regex in a switch statement

-Regex treats each condition as a regular expression. Capture groups land in the automatic $Matches variable, so you can pull values out of each line:

$lines = 'ERROR 404 on /login', 'WARN disk at 91%', 'INFO user signed in'

foreach ($line in $lines) {
    switch -Regex ($line) {
        '^ERROR (\d+)'   { "Error code: $($Matches[1])" }
        '^WARN .* (\d+)%' { "Warning at $($Matches[1]) percent&quo