簡短描述
說明如何使用 參數來處理多個條件語句。
詳細描述
若要檢查文稿或函式中的條件,您可以使用 if
語句。
if
語句可以檢查許多類型的條件,包括變數的值和對象的屬性。
若要檢查多個條件,您可以使用 switch
語句。 語句 switch
類似於一系列 if
語句,但比較簡單。 語句 switch
會列出每個條件和對應的動作。 如果條件相符,則會執行動作。
這很重要
語句會在 switch
比較之前將所有值轉換成字串。
語法
基本 switch
語句的格式如下:
switch (<test-expression>) {
<result1-to-be-matched> {<action>}
<result2-to-be-matched> {<action>}
}
語句的 switch
語法類似下列 if
語句:
if ("$(<result1-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}
if ("$(<result2-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}
表達式包括傳回布爾值的常值(字串或數位)、變數和 scriptblocks。 語句會在 switch
比較之前將所有值轉換成字串。 如需範例,請參閱本文稍後 的字串轉換影響 。
會在 <test-expression>
表示式模式中評估 。 如果表達式傳回一個以上的值,例如數位或其他可列舉型別,語句 switch
會個別評估每個列舉值。
<result-to-be-matched>
是表達式必須解析成單一值。
該值會與輸入值進行比較。
值 default
會保留給沒有其他相符專案時所使用的動作。
switch
語句可以使用 $_
和 $switch
自動變數。 自動變數包含傳遞至 switch
語句的表達式值,可用於評估及使用語句範圍 <result-to-be-matched>
。 如需詳細資訊,請參閱 about_Automatic_Variables。
完整的 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
子句。 它相當於 else
語句中的 if
子句。 每個default
語句中只允許一個switch
子句。
switch
具有下列參數:
- 通配符 - 表示條件為通配符字串。 如果 match 子句不是字串,則會忽略 參數。 此比較不區分大小寫。
- 精確 - 指出比對子句,如果是字串,則必須完全相符。 如果 match 子句不是字串,則會忽略此參數。 此比較不區分大小寫。
- CaseSensitive - 執行區分大小寫的比對。 如果 match 子句不是字串,則會忽略此參數。
-
檔案 - 從檔案取得輸入,而不是從
<test-expression>
。 檔案會一次讀取一行,並由switch
語句評估。 根據預設,比較不區分大小寫。 File 參數僅支援一個檔案。 如果包含多個 File 參數,則只會使用最後一個參數。 如需詳細資訊,請參閱 File 參數範例。 -
Regex - 執行值與條件的正則表示式比對。 如果 match 子句不是字串,則會忽略此參數。
此比較不區分大小寫。 自動
$Matches
變數可用於比對語句區塊內。
注意
指定衝突的值時,例如 Regex 和 通配符,指定的最後一個參數優先,而且會忽略所有衝突的參數。 也允許多個參數實例。 不過,只會使用列出的最後一個參數。
範例
下列範例示範 語句的使用 switch
方式。
簡單比對範例
在下列範例中,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.
使用 break
和 continue
來控制流程
如果值符合多個條件,則會執行每個條件的動作。 若要變更此行為,請使用 break
或 continue
關鍵詞。
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 ( ([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.' }
}
date 物件的 DayOfWeek 屬性是列舉。 雖然列舉可以與其數值或字串值進行比較, switch
但語句會將值轉換成列舉的字串表示。
The string value matches a Thursday.
The expression matches a Thursday.
此行為與語句中-eq
比較的行為if
不同。
if (4 -eq ([datetime]'1 Jan 1970').DayOfWeek) {
'The integer value matches a Thursday.'
}
The value matches a Thursday.
在此範例中,哈希表會傳遞至 switch
語句。 會將 switch
哈希表轉換成字串。
$test = @{
Test = 'test'
Test2 = 'test2'
}
$test.ToString()
System.Collections.Hashtable
請注意,哈希表的字串表示與 測試 索引鍵的值不同。
switch -Exact ($test) {
'System.Collections.Hashtable' { 'Hashtable string coercion' }
'test' { 'Hashtable value' }
}
Hashtable string coercion
用來 switch
測試哈希表中的值
在此範例中 switch
,語句會測試哈希表中值的型別。 我們必須列舉哈希表中的專案,才能測試值。 若要避免字串轉換的複雜性,請使用傳回布爾值的腳本區塊來選取要執行的動作腳本區塊。
$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 ("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.
搭配使用正則表達式 switch
下列範例使用 -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!' }
}
使用讀取檔案的內容 switch
使用 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