共用方式為


about_Switch

簡短描述

說明如何使用 參數來處理多個 if 語句。

詳細描述

若要檢查文稿或函式中的條件,請使用 if 語句。 if語句可以檢查許多類型的條件,包括變數的值和對象的屬性。

若要檢查多個條件,請使用 switch 語句。 switch 語句相當於一系列 if 語句,但更簡單。 語句 switch 會列出每個條件和選擇性動作。 如果條件取得,則會執行動作。

switch語句可以使用 $_$switch 自動變數。 如需詳細資訊,請參閱 about_Automatic_Variables

語法

基本 switch 語句的格式如下:

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

對等 if 語句如下:

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

<test-expression> 是在表達式模式中評估以傳回值的單一表達式。

<result-to-be-matched>是與輸入值比較的表達式。 表達式包括傳回布爾值的常值(字串或數位)、變數和 scriptblocks。

任何無法辨識為數位的未標記值,都會被視為字串。 若要避免混淆或非預期的字串轉換,您應該一律為字元串值加上引號。 在括弧 ()中括住任何表達式,以建立子表達式,以確保正確評估表達式。

請務必瞭解 <result-to-be-matched> 值位於比較表達式的左側。 這表示 的結果 <test-expression> 位於右側,可轉換成左側值的型別進行比較。 如需詳細資訊,請參閱 about_Comparison_Operators

default 會保留給沒有其他相符專案時所使用的動作。

自動 $_ 變數包含傳遞至 switch 語句的表達式值,可用於評估及使用語句範圍 <result-to-be-matched>

完整的 switch 語句語法如下所示:

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

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

如果您沒有使用參數,switch 的行為與使用 Exact 參數的行為相同。 它會針對值執行不區分大小寫的比對。 如果值是集合,則會依照每個元素出現的順序進行評估。

語句 switch 必須至少包含一個 condition 語句。

當值不符合任何條件時,就會觸發 default 子句。 它相當於 if 語句中的 else 子句。 每個default語句中只允許一個switch子句。

switch 具有下列參數:

  • 通配符 - 表示條件為通配符字串。 如果 match 子句不是字串,則會忽略 參數。 此比較不區分大小寫。
  • 精確 - 指出比對子句,如果是字串,則必須完全相符。 如果 match 子句不是字串,則會忽略此參數。 此比較不區分大小寫。
  • CaseSensitive - 執行區分大小寫的比對。 如果 match 子句不是字串,則會忽略此參數。
  • 檔案 - 從檔案取得輸入,而不是從 <test-expression>。 檔案會一次讀取一行,並由 switch 語句評估。 根據預設,比較不區分大小寫。 File 參數僅支援一個檔案。 如果包含多個 File 參數,則只會使用最後一個參數。 如需詳細資訊,請參閱 File 參數範例。
  • Regex - 執行值與條件的正則表示式比對。 如果 match 子句不是字串,則會忽略此參數。 此比較不區分大小寫。 自動 $Matches 變數可用於比對語句區塊內。

注意

指定衝突的值時,例如 Regex通配符,指定的最後一個參數優先,而且會忽略所有衝突的參數。 也允許多個參數實例。 不過,只會使用列出的最後一個參數。

簡單比對範例

在下列範例中,switch 語句會將測試值 3 與每個條件進行比較。 當測試值符合條件時,會執行動作。

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

在此範例中,值會與清單中的每個條件進行比較。 下列 switch 語句的 值為3有兩個條件,示範所有條件都經過測試。

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.

若要指示 switch 在比對之後停止比較,請使用 break 語句。 語句 breakswitch 終止 語句。

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

如果測試值是集合,例如陣列,則集合中的每個項目都會依照其出現的順序進行評估。 下列範例會評估 4 和 2。

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

任何 break 語句都會套用至集合,不適用於每個值,如下列範例所示。 語句 switch 會在值 4 的條件中由 break 語句終止。

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

更複雜的比對範例

在此範例中 switch ,語句會測試哈希表中值的型別。 您必須使用 和表達式,傳回布爾值,以選取要執行的 scriptblock。

$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

在這裡範例中,不是字串或數值資料的物件會傳遞至 switch。 會對 switch 物件執行字串強制,並評估結果。

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

$test.ToString()

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

在此範例中,沒有相符的情況,因此沒有輸出。

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 子句,您可以在沒有其他條件成功時執行動作。

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

若要讓字組 fourteen 符合大小寫,您必須使用 -Wildcard-Regex 參數。

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.

下列範例使用 -Regex 參數。

$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

下列範例示範如何使用腳本區塊作為 switch 語句條件。

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

下列範例會處理包含兩個日期值的陣列。 會 <value-scriptblock> 比較 每個日期的 Year 屬性。 會顯示 <action-scriptblock> 歡迎訊息或 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!' }
}

如果值符合多個條件,則會執行每個條件的動作。 若要變更此行為,請使用 breakcontinue 關鍵詞。

break關鍵詞會停止處理並結束 switch 語句。

continue關鍵詞會停止處理目前的值,但會繼續處理任何後續的值。

下列範例會處理數位數位,並顯示其是否奇數或偶數。 以 關鍵詞略過 continue 負數。 如果遇到非數位,則會使用 break 關鍵詞終止執行。

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

檔案參數範例

使用 switch 語句搭配 File 參數,是逐行處理大型檔案的有效方式。 PowerShell 會將檔案行串流至 switch 語句。 每一行都會個別處理。

您可以在 action 語句中使用 break 關鍵詞,在到達檔尾之前終止處理。 switch 語句比使用 Get-Content 逐行處理大型檔案更有效率。

您可以結合 switch -File-Wildcard-Regex,以彈性且有效率的逐行模式比對。

下列範例會讀取 PowerShell-Docs 存放庫中的 README.md。 它會輸出每一行,直到到達以 ##開頭的行為止。

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

<filename> 自變數會解譯為通配符表達式,但必須只比對一個檔案。 下列範例與上一個範例相同,不同之處在於它在 <filename> 自變數中使用通配符。 此範例的運作方式是通配符模式只符合一個檔案。

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

如果您想要將其視為常值,則必須逸出可解譯為通配符的字元。

$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

另請參閱