Edit

Share via


about_Switch

Short description

Explains how to use a switch to handle multiple conditional statements.

Long description

To check a condition in a script or function, you can use an if statement. The if statement can check many types of conditions, including the value of variables and the properties of objects.

To check multiple conditions, you can use a switch statement. The switch statement is similar to a series of if statements, but it's simpler. The switch statement lists each condition and the corresponding action. If a condition matches, the action is performed.

Important

The switch statement converts all values to strings before comparison.

Syntax

A basic switch statement has the following format:

switch (<test-expression>) {
    <result1-to-be-matched> {<action>}
    <result2-to-be-matched> {<action>}
}

The syntax of a switch statement is similar to the following if statements:

if ("$(<result1-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}
if ("$(<result2-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}

Expressions include literal values (strings or numbers), variables, and scriptblocks that return a boolean value. The switch statement converts all values to strings before comparison. For an example, see Impact of string conversion later in this article.

The <test-expression> is evaluated in expression mode. If the expression returns more than one value, such as an array or other enumerable type, the switch statement evaluates each enumerated value separately.

The <result-to-be-matched> is an expression must resolve to a single value. That value is compared to the input value.

The value default is reserved for the action used when there are no other matches.

The switch statement can use the $_ and $switch automatic variables. The automatic variable contains the value of the expression passed to the switch statement and is available for evaluation and use within the scope of the <result-to-be-matched> statements. For more information, see about_Automatic_Variables.

The complete switch statement syntax is as follows:

switch [-Regex | -Wildcard | -Exact] [-CaseSensitive] (<test-expression>) {
    string | number | variable | { <value-scriptblock> }
        { <action-scriptblock> }
    default { <action-scriptblock> } # optional
}

or

switch [-Regex | -Wildcard | -Exact] [-CaseSensitive] -File filename {
    string | number | variable | { <value-scriptblock> }
        { <action-scriptblock> }
    default { <action-scriptblock> }  # optional
}

If you don't use parameters, switch behaves the same as using the Exact parameter. It performs a case-insensitive match for the value. If the value is a collection, each element is evaluated in the order in which it appears.

The switch statement must include at least one condition statement.

The default clause is triggered when the value doesn't match any of the conditions. It's equivalent to an else clause in an if statement. Only one default clause is permitted in each switch statement.

switch has the following parameters:

  • Wildcard - Indicates that the condition is a wildcard string. If the match clause isn't a string, the parameter is ignored. The comparison is case-insensitive.
  • Exact - Indicates that the match clause, if it's a string, must match exactly. If the match clause isn't a string, this parameter is ignored. The comparison is case-insensitive.
  • CaseSensitive - Performs a case-sensitive match. If the match clause is not a string, this parameter is ignored.
  • File - Takes input from a file rather than a <test-expression>. The file is read a line at a time and evaluated by the switch statement. By default, the comparison is case-insensitive. The File parameter only supports one file. If multiple File parameters are included, only the last one is used. For more information see the File parameter examples.
  • Regex - Performs regular expression matching of the value to the condition. If the match clause isn't a string, this parameter is ignored. The comparison is case-insensitive. The $Matches automatic variable is available for use within the matching statement block.

Note

When specifying conflicting values, like Regex and Wildcard, the last parameter specified takes precedence, and all conflicting parameters are ignored. Multiple instances of parameters are also permitted. However, only the last parameter listed is used.

Examples

The following examples demonstrate the use of the switch statement.

Simple match examples

In the following example, the switch statement compares the test value 3 to each of the conditions. When the test value matches the condition, the action is performed.

switch (3) {
    1 { "It's one."   }
    2 { "It's two."   }
    3 { "It's three." }
    4 { "It's four."  }
}
It's three.

In this example, the value is compared to each condition in the list. The following switch statement has two conditions for a value of 3, which demonstrates that all conditions are tested.

switch (3) {
    1 { "It's one."    }
    2 { "It's two."    }
    3 { "It's three."  }
    4 { "It's four."   }
    3 { "Three again." }
}
It's three.
Three again.

Use break and continue to control the flow

If the value matches multiple conditions, the action for each condition is executed. To change this behavior, use the break or continue keywords.

The break keyword stops processing and exits the switch statement.

The continue keyword stops processing the current value, but continues processing any subsequent values.

The following example processes an array of numbers and displays if they're odd or even. Negative numbers are skipped with the continue keyword. If a non-number is encountered, execution is terminated with the break keyword.

switch (1,4,-1,3,"Hello",2,1) {
    {$_ -lt 0}           { continue }
    {$_ -isnot [int32]}  { break }
    {$_ % 2}             { "$_ is Odd" }
    {-not ($_ % 2)}      { "$_ is Even" }
}
1 is Odd
4 is Even
3 is Odd

Impact of string conversion

All values, both input and the comparison value are converted to strings for comparison. To avoid unintended string conversion, use script blocks to evaluate the switch value.

switch ( ([datetime]'1 Jan 1970').DayOfWeek ) {
    4            { 'The integer value matches a Thursday.' }
    "4"          { 'The numeric string matches a Thursday.' }
    "Thursday"   { 'The string value matches a Thursday.' }
    { 4 -eq $_ } { 'The expression matches a Thursday.' }
}

The DayOfWeek property of the date object is an enumeration. While enumerations can be compared to their numeric or string values, the switch statement converts the value to a the string representation of the enumeration.

The string value matches a Thursday.
The expression matches a Thursday.

This behavior is different from the behavior of the -eq comparison in an if statement.

if (4 -eq ([datetime]'1 Jan 1970').DayOfWeek) {
    'The integer value matches a Thursday.'
}
The value matches a Thursday.

In this example, a hashtable is passed to the switch statement. The switch converts the hashtable to a string.

$test = @{
    Test  = 'test'
    Test2 = 'test2'
}

$test.ToString()
System.Collections.Hashtable

Notice that the string representation of the hashtable is not the same as the value of the Test key.

switch -Exact ($test) {
    'System.Collections.Hashtable' { 'Hashtable string coercion' }
    'test'                         { 'Hashtable value' }
}
Hashtable string coercion

Use switch to test the values in a hashtable

In this example, the switch statement is testing for the type of the value in the hashtable. We must enumerate the items in the hashtable before we can test the values. To avoid the complications of string conversion, use a script block that returns a boolean value to select the action scriptblock to execute.

$var = @{A = 10; B = 'abc'}

foreach ($key in $var.Keys) {
    switch ($var[$key].GetType()) {
        { $_ -eq [int32]  }  { "$key + 10 = $($var[$key] + 10)" }
        { $_ -eq [string] }  { "$key = $($var[$key])"           }
    }
}
A + 10 = 20
B = abc

Use wildcards with switch

In this example, there is no matching case so there is no output.

switch ("fourteen") {
    1     { "It's one.";   break }
    2     { "It's two.";   break }
    3     { "It's three."; break }
    4     { "It's four.";  break }
    "fo*" { "That's too many."   }
}

By adding the default clause, you can perform an action when no other conditions succeed.

switch ("fourteen") {
    1       { "It's one.";   break }
    2       { "It's two.";   break }
    3       { "It's three."; break }
    4       { "It's four.";  break }
    "fo*"   { "That's too many."   }
    default { "No matches"         }
}
No matches

For the word fourteen to match a case you must use the -Wildcard or -Regex parameter.

switch -Wildcard ("fourteen") {
    1     { "It's one.";   break }
    2     { "It's two.";   break }
    3     { "It's three."; break }
    4     { "It's four.";  break }
    "fo*" { "That's too many."   }
}
That's too many.

Use regular expressions with switch

The following example uses the -Regex parameter.

$target = 'https://bing.com'
switch -Regex ($target) {
    '^ftp\://.*$'
        {
            "$_ is an ftp address"
            break
        }
    '^\w+@\w+\.com|edu|org$'
        {
            "$_ is an email address"
            break
        }
    '^(http[s]?)\://.*$'
        {
            "$_ is a web address that uses $($Matches[1])"
            break
        }
}
https://bing.com is a web address that uses https

The following example demonstrates the use of script blocks as switch statement conditions.

switch ("Test") {
    { $_ -is [string] } { "Found a string" }
    "Test"              { "This $_ executes as well" }
}
Found a string
This Test executes as well

The following example processes an array containing two date values. The <value-scriptblock> compares the Year property of each date. The <action-scriptblock> displays a welcome message or the number of days until the beginning of the year 2022.

switch ((Get-Date 1-Jan-2022), (Get-Date 25-Dec-2021)) {
    { $_.Year -eq 2021 }
        {
            $days = ((Get-Date 1/1/2022) - $_).Days
            "There are $days days until 2022."
        }
    { $_.Year -eq 2022 } { 'Welcome to 2022!' }
}

Read the content of a file with switch

Using the switch statement with the File parameter is an efficient way to process large files line by line. PowerShell streams the lines of the file to the switch statement. Each line is processed individually.

You can terminate the processing before reaching the end of the file by using the break keyword in the action statement. The switch statement is more efficient than using Get-Content to process large files line by line.

You can combine switch -File with -Wildcard or -Regex for flexible and efficient line-by-line pattern matching.

The following example reads the README.md in the PowerShell-Docs repository. It outputs each line until it reaches the line that starts with ##.

switch -Regex -File .\README.md {
    '^##\s' { break }
    default { $_; continue }
}

The <filename> argument accepts wildcard expressions, but it must match only one file. The following example is the same as the previous one except it uses a wildcard in the <filename> argument. This example works because the wildcard pattern matches only one file.

switch -Regex -File .\README.* {
    '^##\s' { break }
    default { $_; continue }
}

You must escape characters that can be interpreted as wildcards if you want them to be treated as literals.

$file = (New-Item -Path 'Temp:\Foo[0]' -Value Foo -Force).FullName
switch -File $file { Foo { 'Foo' } }
# No files matching '...\Temp\Foo[0]' were found.

$fileEscaped = [WildcardPattern]::Escape($file)
switch -File $fileEscaped { foo { 'Foo' } }
# Foo

See also