switch 语句中多个值的 PowerShell 语法是什么?

问题描述 投票:0回答:10

我基本上想这样做:

switch($someString.ToLower())
{
    "y", "yes" { "You entered Yes." }
    default { "You entered No." }
}
powershell switch-statement
10个回答
113
投票
switch($someString.ToLower()) 
{ 
    {($_ -eq "y") -or ($_ -eq "yes")} { "You entered Yes." } 
    default { "You entered No." } 
}

65
投票

我发现这有效并且看起来更具可读性:

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

“-contains”运算符执行不区分大小写的搜索,因此您不需要使用“ToLower()”。如果您确实希望它区分大小写,可以使用“-ccontains”代替。


49
投票

您应该能够对您的值使用通配符:

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 语句


11
投票

对 derekerdmann 的帖子进行了轻微修改,以满足使用正则表达式的交替运算符“|”(管道)的原始请求。

对于正则表达式新手来说,理解和阅读也稍微容易一些。

请注意,在使用正则表达式时,如果您不放置字符串字符“^”(脱字符/抑扬符)的开头和/或字符串字符“$”(美元)的结尾,那么您可能会得到意外/不直观的行为(例如匹配“昨天”或“为什么”)。

在选项周围放置分组字符“()”(括号)可以减少为每个选项放置字符串开头和结尾字符的需要。如果没有它们,如果您不熟悉正则表达式,您可能会得到意想不到的行为。当然,如果您不处理用户输入,而是处理一组已知字符串,则无需分组以及字符串字符的开头和结尾,它将更具可读性。

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." } 
}

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

您可以以这种方式任意分支、级联和合并案例,只要目标案例位于分别重新分配 $_ 变量的案例的下方/之后。


n.b.尽管这种行为很可爱,但它似乎表明 PowerShell 解释器并没有像人们希望或假设的那样有效地实现 switch/case。其一,使用 ISE 调试器单步执行建议不要优化查找、散列或二进制分支,而是依次测试每种情况,就像许多 if-else 语句一样。 (因此,请考虑将最常见的案例放在第一位。)此外,如本答案所示,PowerShell 在满足案例后继续测试案例。残酷的是,.NET CIL 中甚至恰好有一个特殊优化的“switch”操作码,由于这种行为,PowerShell 无法利用它。


6
投票
支持输入y|ye|yes且不区分大小写。

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

6
投票
这是另一张。无论如何,开关不区分大小写。 -eq 左边有一个数组将返回它等于的东西,并且返回的任何东西都是 true。

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

4
投票
js2010

给出的答案很有价值,特别是在问题的上下文中。但是,在人们寻找如何使用 Switch 语句的示例的背景下,它可以使用其工作原理的解释以及一些潜在的问题。

-eq

运算符,
左侧有一个数组,将仅过滤掉与右侧给出的单个值匹配的项目。如果返回单个值,则结果是单个值,但如果返回多个值,则结果是数组。

Switch 语句创建一个需要布尔值的上下文,并且在该上下文中,如果是 ''、""、

-eq

,则 
$false 比较的结果 确定为
$null
, 0,即值为 0.0,否则视为
$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
的结果也是
''
的单个项目,它会转换为布尔值
$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
返回一个空字符串数组,然后将其转换为布尔值
$true
,将正确匹配
''
-eq: '' does Match
-ceq '' does Match
-eq: 'C' does Match
-eq: 'd' does Match
-ceq 'd' does Match
'E' doesn't Match



-3
投票
$someString

示例都有效。 [已修复,感谢js2010]

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

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



-5
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.