簡體   English   中英

switch 語句中多個值的 PowerShell 語法是什么?

[英]What's the PowerShell syntax for multiple values in a switch statement?

我基本上想這樣做:

switch($someString.ToLower())
{
    "y", "yes" { "You entered Yes." }
    default { "You entered No." }
}
switch($someString.ToLower()) 
{ 
    {($_ -eq "y") -or ($_ -eq "yes")} { "You entered Yes." } 
    default { "You entered No." } 
}

我發現這有效並且似乎更具可讀性:

switch($someString)
{
    { @("y", "yes") -contains $_ } { "You entered Yes." }
    default { "You entered No." }
}

“-contains”運算符執行不區分大小寫的搜索,因此您不需要使用“ToLower()”。 如果您確實希望它區分大小寫,則可以改用“-ccontains”。

您應該能夠為您的值使用通配符:

switch -wildcard ($someString.ToLower())
{
    "y*" { "You entered Yes." }
    default { "You entered No." }
}

也允許使用正則表達式。

switch -regex ($someString.ToLower())
{
    "y(es)?" { "You entered Yes." }
    default { "You entered No." }
}

PowerShell 開關文檔: 使用 Switch 語句

switch($someString.ToLower())
{
    "yes"   { $_ = "y" }
    "y"     { "You entered Yes." }
    default { "You entered No." }
}

您可以以這種方式任意分支、級聯和合並案例,只要目標案例位於 $_ 變量分別重新分配的案例的下方/之后


nb 盡管這種行為很可愛,但它似乎表明 PowerShell 解釋器並沒有像人們希望或假設的那樣有效地實現 switch/case。 一方面,使用 ISE 調試器單步調試表明,不是優化查找、散列或二進制分支,而是依次測試每個案例,就像許多 if-else 語句一樣。 (如果是這樣,請考慮將最常見的案例放在首位。)此外,如本答案所示,PowerShell 在滿足一個案例后繼續測試案例。 殘酷的是,.NET CIL 中甚至有一個特殊的優化“開關”操作碼可用,由於這種行為,PowerShell 無法利用。

支持輸入 y|ye|yes 並且不區分大小寫。

switch -regex ($someString.ToLower()) {
        "^y(es?)?$" {
            "You entered Yes." 
        }
        default { "You entered No." }
}

使用正則表達式的交替運算符“|”(管道)對 derekerdmann 的帖子進行了輕微修改以滿足原始請求。

正則表達式新手也更容易理解和閱讀。

請注意,在使用正則表達式時,如果您沒有將字符串字符“^”(插入符號/circumflex)的開頭和/或字符串字符“$”(美元)的結尾放置,那么您可能會遇到意外/不直觀的行為(例如匹配“昨天”或“為什么”)。

在選項周圍放置分組字符“()”(括號)減少了為每個選項放置字符串開頭和結尾字符的需要。 沒有它們,如果您不精通正則表達式,您可能會遇到意想不到的行為。 當然,如果您不處理用戶輸入,而是處理一些已知字符串,則無需對字符串字符進行分組以及開始和結束,它的可讀性會更高。

switch -regex ($someString) #many have noted ToLower() here is redundant
{
        #processing user input
    "^(y|yes|indubitably)$" { "You entered Yes." }

        # not processing user input
    "y|yes|indubitably" { "Yes was the selected string" } 
    default { "You entered No." } 
}

這是另一個。 無論如何,開關不區分大小寫。 -eq 左邊的數組將返回它等於的東西,並且返回的任何東西都是真的。

switch($someString)
{
  { 'y', 'yes' -eq $_ } { 'You entered Yes.' }
  default               { 'You entered No.'  }
}

js2010給出的答案是有價值的,尤其是在題目的上下文中。 但是,在人們搜索如何使用 Switch 語句的示例的上下文中,它可能會解釋其工作原理以及一些潛在問題。

-eq運算符, 左邊有一個數組,將只過濾掉與右邊給定的單個值匹配的項目。 如果返回單個值,則結果為單個值,但如果返回多個值,則結果為數組。

Switch 語句創建一個預期值為 Boolean 的上下文,並且在該上下文中,如果值為 ''、""、 $null 、0 或 0.0,則-eq比較的結果被確定$false , 否則,它被認為是$true 這意味着測試空字符串將失敗,如下例所示。 以下示例還展示了如何使用-ceq進行區分大小寫的測試,並展示了在不使用break語句時 Switch 有時有用的行為:

foreach ($someString in '', 'C', 'd', 'E') {
    switch($someString) {
        { '', 'b', 'c', 'd', 'g' -eq $_ }   { "-eq: '$_' does Match" }
        { '', 'b', 'c', 'd', 'g' -ceq $_ }  { "-ceq '$_' does Match" }
        default                 { "'$_' doesn't Match" }
    }
}

正如您在以下示例結果中看到的,即使''在要檢查的項目列表中, -eq的結果是''的單個項目,它被轉換為 Boolean 值$false並導致''被視為不在列表中。

'' doesn't Match
-eq: 'C' does Match
-eq: 'd' does Match
-ceq 'd' does Match
'E' doesn't Match

另一個問題,如以下示例所示,是當您將單個測試值放在左側,而要測試的項目數組放在右側時。

foreach ($someString in '', 'C', 'd', 'E') {
    switch($someString) {
        { $_ -eq '', 'b', 'c', 'd', 'g' }   { "-eq: '$_' does Match" }
        { $_ -eq '', 'b', 'c', 'd', 'g' }  { "-ceq '$_' does Match" }
        default                 { "'$_' doesn't Match" }
    }
}

正如您在以下示例結果中看到的,沒有任何匹配項:

'' doesn't Match   
'C' doesn't Match  
'd' doesn't Match  
'E' doesn't Match

這個問題的解決方法是始終在-eq運算符的左側放置要測試的項目數組,並在測試空字符串時讓-eq返回一個包含 2 個空字符串的數組。 -eq返回的空字符串數組是一個非$null值,並被轉換為$true

foreach ($someString in '', 'C', 'd', 'E') {
    switch($someString) {
        { '', '', 'b', 'c', 'd', 'g' -eq $_ }   { "-eq: '$_' does Match" }
        { '', '', 'b', 'c', 'd', 'g' -ceq $_ }  { "-ceq '$_' does Match" }
        default                 { "'$_' doesn't Match" }
    }
}

正如您在以下示例中看到的,讓-eq-ceq返回一個空字符串數組,然后將其轉換為 Boolean $true ,將正確匹配''

-eq: '' does Match
-ceq '' does Match
-eq: 'C' does Match
-eq: 'd' does Match
-ceq 'd' does Match
'E' doesn't Match

該開關在 PowerShell 5.1 中似乎不區分大小寫。 下面所有四個$someString示例都有效。 [這不正確——js2010]

$someString = "YES"
$someString = "yes"
$someString = "yEs"
$someString = "y"

switch ($someString) {
   {"y","yes"} { "You entered Yes." }
   Default { "You didn't enter Yes."}
}

這是我的$PSVersionTable數據。

Name                           Value
----                           -----
PSVersion                      5.1.17763.771
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17763.771
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

在為與您一樣的問題尋找解決方案后,我在這里找到了這個小主題。 事先我得到了一個更流暢的解決方案,案例陳述

switch($someString) #switch is caseINsensitive, so you don't need to lower
{
    { 'y' -or 'yes' } { "You entered Yes." }
    default { "You entered No." }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM