PowerShell Switch Statement: Cleaner Conditionals

You’ve written a five-branch if/elseif chain to handle different status codes, and it already looks messy. The PowerShell switch statement was designed for exactly this situation: multiple conditions testing the same value, handled cleanly in a single readable block. Beyond basic value matching, PowerShell’s switch supports wildcards, regex patterns, and can even switch on arrays — features that most developers don’t realize exist. This guide shows you everything the switch statement can do.
Basic Switch Syntax
The switch statement evaluates an expression and runs the first matching case block:
$statusCode = 404
switch ($statusCode) {
200 { Write-Output 'OK' }
201 { Write-Output 'Created' }
400 { Write-Warning 'Bad Request' }
401 { Write-Warning 'Unauthorized' }
403 { Write-Warning 'Forbidden' }
404 { Write-Warning 'Not Found' }
500 { Write-Error 'Internal Server Error' }
default { Write-Output "Unknown status: $statusCode" }
}
WARNING: Not Found
Each case value is tested for equality. The default block runs if no case matches. String comparisons in switch are case-insensitive by default, just like -eq.
Default Case
The default block acts as a catch-all and is always a good practice to include:
$env = 'STAGING'
switch ($env) {
'DEV' { $dbServer = 'devdb01.corp.local' }
'STAGING' { $dbServer = 'stgdb01.corp.local' }
'PROD' { $dbServer = 'proddb01.corp.local' }
default {
throw "Unknown environment: $env. Valid values: DEV, STAGING, PROD"
}
}
Write-Output "Database: $dbServer"
Database: stgdb01.corp.local
Switch with Wildcards (-Wildcard)
The -Wildcard flag enables * and ? wildcard matching in case values:
$filename = 'backup_2026-05-04.zip'
switch -Wildcard ($filename) {
'*.zip' { Write-Output 'Archive file' }
'*.log' { Write-Output 'Log file' }
'backup*' { Write-Output 'Backup file' }
'*.tmp' { Write-Output 'Temporary file — can delete' }
}
Archive file
Backup file
Notice that both matching cases ran. Unlike many languages, PowerShell’s switch has fall-through by default — if multiple cases match, all their blocks execute. Use break to stop after the first match when that’s the desired behavior.
Switch with Regex (-Regex)
The -Regex flag matches case values as regular expressions:
$logEntry = 'ERROR: Connection timed out after 30s'
switch -Regex ($logEntry) {
'^ERROR' { Write-Output "Error detected: $logEntry"; break }
'^WARNING' { Write-Output "Warning: $logEntry"; break }
'^INFO' { Write-Output "Info: $logEntry"; break }
'\d+ ?ms' { Write-Output "Timing data found"; break }
default { Write-Output "Unclassified: $logEntry" }
}
# The automatic variable $Matches holds capture groups
$ipAddress = '192.168.1.100'
switch -Regex ($ipAddress) {
'^10\.' { Write-Output 'RFC1918 Class A' }
'^172\.1[6-9]\.' { Write-Output 'RFC1918 Class B' }
'^192\.168\.' { Write-Output 'RFC1918 Class C' }
default { Write-Output 'Public IP' }
}
Error detected: ERROR: Connection timed out after 30s
RFC1918 Class C
Switching on Arrays
A rarely used but powerful feature: if you pass an array to switch, it evaluates each element against the cases:
$ports = @(80, 443, 22, 3389, 8080)
switch ($ports) {
22 { Write-Output "Port 22: SSH" }
80 { Write-Output "Port 80: HTTP" }
443 { Write-Output "Port 443: HTTPS" }
3389 { Write-Warning "Port 3389: RDP — restrict access" }
default { Write-Output "Port $_ : Unknown service" }
}
Port 80: HTTP
Port 443: HTTPS
Port 22: SSH
WARNING: Port 3389: RDP — restrict access
Port 8080 : Unknown service
Inside a switch block processing an array, $_ holds the current element. This eliminates the need for a separate foreach loop when you’re classifying each item in a collection.
Fall-Through Behavior
By default, every matching case runs. Use break to stop after the first match:
$color = 'blue'
# Without break — all matching cases run
switch ($color) {
'blue' { Write-Output 'Matches: blue' }
'blue' { Write-Output 'Also matches: blue' } # Duplicate — runs too
default { Write-Output 'Default' }
}
# With break — stops at first match
switch ($color) {
'blue' { Write-Output 'First match'; break }
'blue' { Write-Output 'Never runs' }
default { Write-Output 'Never runs' }
}
Matches: blue
Also matches: blue
Default
First match
In practice, include break in every case block unless you specifically want multiple cases to fire. The fall-through default surprises most developers coming from C#, Java, or JavaScript where fall-through requires an explicit goto.
Common Errors and Fixes
-
Fall-through to multiple cases when not expected: Multiple matching cases all execute unless you add
break. If your switch seems to run too many blocks, addbreakat the end of each case. -
Regex flag needed for pattern matching: Without
-Regex, case values are compared literally.switch ($str) { '^\d+' { } }only matches the literal string^\d+, not strings that match the regex pattern. Add-Regexto the switch keyword.
Related Cmdlets / See Also
Wrapping Up
PowerShell’s switch statement is more powerful than most people realize: it handles wildcards, regex, and entire arrays without extra loops. Use it in place of long if/elseif chains for cleaner, more maintainable code. Always add break unless you want multiple cases to fire. Your next step: refactor your longest if/elseif chain into a switch statement and see how much cleaner it becomes.


