PowerShell Switch Statement: Cleaner Conditionals

PowerShell Switch Statement: Cleaner Conditionals

PowerShell Tips Editor 4 min read
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, add break at 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 -Regex to 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.

Send-Item -To