简体   繁体   English

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

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

I basically want to do this:我基本上想这样做:

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

I found that this works and seems more readable:我发现这有效并且似乎更具可读性:

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

The "-contains" operator performs a non-case sensitive search, so you don't need to use "ToLower()". “-contains”运算符执行不区分大小写的搜索,因此您不需要使用“ToLower()”。 If you do want it to be case sensitive, you can use "-ccontains" instead.如果您确实希望它区分大小写,则可以改用“-ccontains”。

You should be able to use a wildcard for your values:您应该能够为您的值使用通配符:

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

Regular expressions are also allowed.也允许使用正则表达式。

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

PowerShell switch documentation: Using the Switch Statement PowerShell 开关文档: 使用 Switch 语句

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

You can arbitrarily branch, cascade, and merge cases in this fashion, as long as the target case is located below/after the case or cases where the $_ variable is respectively reassigned.您可以以这种方式任意分支、级联和合并案例,只要目标案例位于 $_ 变量分别重新分配的案例的下方/之后


nb As cute as this behavior is, it seems to reveal that the PowerShell interpreter is not implementing switch/case as efficiently as one might hope or assume. nb 尽管这种行为很可爱,但它似乎表明 PowerShell 解释器并没有像人们希望或假设的那样有效地实现 switch/case。 For one, stepping with the ISE debugger suggests that instead of optimized lookup, hashing, or binary branching, each case is tested in turn, like so many if-else statements.一方面,使用 ISE 调试器单步调试表明,不是优化查找、散列或二进制分支,而是依次测试每个案例,就像许多 if-else 语句一样。 (If so, consider putting your most common cases first.) Also, as shown in this answer, PowerShell continues testing cases after having satisfied one. (如果是这样,请考虑将最常见的案例放在首位。)此外,如本答案所示,PowerShell 在满足一个案例后继续测试案例。 And cruelly enough, there even happens to be a special optimized 'switch' opcode available in .NET CIL which, because of this behavior, PowerShell can't take advantage of.残酷的是,.NET CIL 中甚至有一个特殊的优化“开关”操作码可用,由于这种行为,PowerShell 无法利用。

Supports entering y|ye|yes and case insensitive.支持输入 y|ye|yes 并且不区分大小写。

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

A slight modification to derekerdmann's post to meet the original request using regex's alternation operator "|"(pipe).使用正则表达式的交替运算符“|”(管道)对 derekerdmann 的帖子进行了轻微修改以满足原始请求。

It's also slightly easier for regex newbies to understand and read.正则表达式新手也更容易理解和阅读。

Note that while using regex, if you don't put the start of string character "^"(caret/circumflex) and/or end of string character "$"(dollar) then you may get unexpected/unintuitive behavior (like matching "yesterday" or "why").请注意,在使用正则表达式时,如果您没有将字符串字符“^”(插入符号/circumflex)的开头和/或字符串字符“$”(美元)的结尾放置,那么您可能会遇到意外/不直观的行为(例如匹配“昨天”或“为什么”)。

Putting grouping characters "()"(parentheses) around the options reduces the need to put start and end of string characters for each option.在选项周围放置分组字符“()”(括号)减少了为每个选项放置字符串开头和结尾字符的需要。 Without them, you'll get possibly unexpected behavior if you're not savvy with regex.没有它们,如果您不精通正则表达式,您可能会遇到意想不到的行为。 Of course, if you're not processing user input, but rather some set of known strings, it will be more readable without grouping and start and end of string characters.当然,如果您不处理用户输入,而是处理一些已知字符串,则无需对字符串字符进行分组以及开始和结束,它的可读性会更高。

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

Here's another one.这是另一个。 Switch is case insensitive anyway.无论如何,开关不区分大小写。 -eq with an array on the left will return the thing it's equal to, and anything returned is true. -eq 左边的数组将返回它等于的东西,并且返回的任何东西都是真的。

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

The answer given by js2010 has value, especially in the context of the question. js2010给出的答案是有价值的,尤其是在题目的上下文中。 But, in the context of people searching for examples of how to use the Switch statement, it could use an explanation of why it works, and a couple of potential problems.但是,在人们搜索如何使用 Switch 语句的示例的上下文中,它可能会解释其工作原理以及一些潜在问题。

The -eq operator, with an array on the left , will filter out only items that match the single value given on the right. -eq运算符, 左边有一个数组,将只过滤掉与右边给定的单个值匹配的项目。 If a single value is returned, then the results is a single value, but if more than one value is returned, then the results is an array.如果返回单个值,则结果为单个值,但如果返回多个值,则结果为数组。

The Switch statement creates a context where a Boolean value is expected, and, in that context, the results of the -eq comparison is determined to be $false if it is '', "", $null , 0, or 0.0 in value, else, it is considered to be $true . Switch 语句创建一个预期值为 Boolean 的上下文,并且在该上下文中,如果值为 ''、""、 $null 、0 或 0.0,则-eq比较的结果被确定$false , 否则,它被认为是$true This means that testing for an empty string will, as in the following example, fail.这意味着测试空字符串将失败,如下例所示。 The following example also shows how to do a case sensitive test using -ceq , and shows the sometimes useful behavior of Switch when the break statement isn't used:以下示例还展示了如何使用-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" }
    }
}

As you seen in the following example results, even though '' is in the list of items to check for, the result of -eq is a single item of '' , which is converted to the Boolean value $false and results in '' being treated as if it isn't in the list.正如您在以下示例结果中看到的,即使''在要检查的项目列表中, -eq的结果是''的单个项目,它被转换为 Boolean 值$false并导致''被视为不在列表中。

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

The other problem, as in the following example, is when you place the single test value on the left, and the array of items to test against on right.另一个问题,如以下示例所示,是当您将单个测试值放在左侧,而要测试的项目数组放在右侧时。

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

As you can see in the following example results, nothing matches:正如您在以下示例结果中看到的,没有任何匹配项:

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

This problems are solved by always having the array of items to test against on the left side of the -eq operator, and by having -eq return an array of 2 empty strings when testing for an empty string.这个问题的解决方法是始终在-eq运算符的左侧放置要测试的项目数组,并在测试空字符串时让-eq返回一个包含 2 个空字符串的数组。 The array of empty strings returned by -eq is a non $null value, and is converted to $true . -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" }
    }
}

As you can see in the following example, having -eq and -ceq return an array of empty strings, which is then converted Boolean $true , will correctly 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

The switch doesn't appear to be case sensitive in PowerShell 5.1.该开关在 PowerShell 5.1 中似乎不区分大小写。 All four of the $someString examples below work.下面所有四个$someString示例都有效。 [ This is not correct -- js2010] [这不正确——js2010]

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

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

Here is my $PSVersionTable data.这是我的$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

After searching a solution for the same problem like you, I've found this small topic here.在为与您一样的问题寻找解决方案后,我在这里找到了这个小主题。 In advance I got a much smoother solution for this switch, case statement事先我得到了一个更流畅的解决方案,案例陈述

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