Wie lautet die PowerShell-Syntax für mehrere Werte in einer switch-Anweisung?

78

Grundsätzlich möchte ich das tun:

switch($someString.ToLower())
{
    "y", "yes" { "You entered Yes." }
    default { "You entered No." }
}
Micah
quelle

Antworten:

87
switch($someString.ToLower()) 
{ 
    {($_ -eq "y") -or ($_ -eq "yes")} { "You entered Yes." } 
    default { "You entered No." } 
}
Fletcher
quelle
29
kann auch, {$_ -in "y","yes"}aber ich bin mir nicht sicher seit welcher PS-Version.
Tkokasih
5
-eq unterscheidet nicht zwischen Groß- und Kleinschreibung, wenn ein Zeichenfolgenvergleich durchgeführt wird, sodass ToLower nicht benötigt wird
Bogdan Gavril MSFT
4
Ebenso können Sie dies tun { "y", "yes" -contains $_ } . Auch dies unterscheidet nicht zwischen Groß- und Kleinschreibung, sodass auch "JA" und "Ja" usw. funktionieren.
TurtleZero
49

Ich fand, dass dies funktioniert und lesbarer erscheint:

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

Der Operator "-contains" führt eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durch, sodass Sie "ToLower ()" nicht verwenden müssen. Wenn Sie möchten, dass zwischen Groß- und Kleinschreibung unterschieden wird, können Sie stattdessen "-ccontains" verwenden.

Jimmy
quelle
45

Sie sollten in der Lage sein, einen Platzhalter für Ihre Werte zu verwenden:

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

Reguläre Ausdrücke sind ebenfalls zulässig.

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

PowerShell-Switch-Dokumentation: Verwenden der Switch-Anweisung

derekerdmann
quelle
1
Dies ist eine großartige Lösung, obwohl ich "technisch", da ich nach separaten Werten gefragt habe, Fletcher als Antwort markiert habe.
Micah
2
Fair genug, obwohl ein anderer regulärer Ausdruck wahrscheinlich dasselbe tun könnte.
Derekerdmann
2
Der Regex-Ansatz wäre prägnanter.
mseery
3
Sie benötigen das nicht, ToLower()da bei der Gleichheit von Zeichenfolgen in PowerShell standardmäßig die Groß- und Kleinschreibung nicht berücksichtigt wird.
Dan-Gph
7
switch($someString.ToLower())
{
    "yes"   { $_ = "y" }
    "y"     { "You entered Yes." }
    default { "You entered No." }
}

Sie können Fälle auf diese Weise willkürlich verzweigen, kaskadieren und zusammenführen, solange sich der Zielfall unter / nach dem Fall befindet oder Fälle, in denen die Variable $ _ jeweils neu zugewiesen wird.


nb So niedlich dieses Verhalten auch ist, es scheint zu zeigen, dass der PowerShell-Interpreter Switch / Case nicht so effizient implementiert, wie man es sich erhoffen oder annehmen könnte. Zum einen deutet ein Schritt mit dem ISE-Debugger darauf hin, dass anstelle einer optimierten Suche, eines Hashings oder einer binären Verzweigung jeder Fall nacheinander getestet wird, wie so viele if-else-Anweisungen. (Wenn ja, sollten Sie Ihre häufigsten Fälle an die erste Stelle setzen.) Wie in dieser Antwort gezeigt, testet PowerShell auch weiterhin Fälle, nachdem Sie einen erfüllt haben. Und grausamerweise gibt es in .NET CIL sogar einen speziell optimierten "Switch" -Opcode, den PowerShell aufgrund dieses Verhaltens nicht nutzen kann.

Glenn Slayden
quelle
2
Es ist nicht süß - es ist dokumentiert. Fügen Sie eine break-Anweisung hinzu, wenn nachfolgende Zweige nicht ausgewertet werden sollen.
Frank
2
@Frank Fair genug, "süß" war möglicherweise nicht das beste Wort, um sich auf ein Keyword-Verhalten zu beziehen, das gegenüber seiner historischen Semantik in zahlreichen Sprachen seit 'C' (1975) oder früher geändert oder untypisch ist.
Glenn Slayden
5

Unterstützt die Eingabe von y | ye | yes und die Groß- und Kleinschreibung wird nicht berücksichtigt.

switch -regex ($someString.ToLower()) {
        "^y(es?)?$" {
            "You entered Yes." 
        }
        default { "You entered No." }
}
Doug Finke
quelle
13
Tatsächlich stimmt Ihr Ausdruck "[yes]" mit jedem Vorkommen der Zeichen 'y', 'e' oder 's' irgendwo in $ someString überein. Selbst wenn $ someString "nein! Nein! Nein! S" ist, gibt dieser Schalterblock "Sie haben Ja eingegeben" zurück. wegen der nachgestellten 's'. Um mit y | ye | yes übereinzustimmen, sollte der Ausdruck "^ y (es?)? $" Sein.
Speck
5

Eine geringfügige Änderung an derekerdmanns Post, um die ursprüngliche Anforderung mit dem Regex-Wechseloperator "|" (Pipe) zu erfüllen.

Es ist auch etwas einfacher für Regex-Neulinge, zu verstehen und zu lesen.

Beachten Sie, dass bei Verwendung von Regex, wenn Sie den Anfang des Zeichenfolgenzeichens "^" (Caret / Circumflex) und / oder das Ende des Zeichenfolgenzeichens "$" (Dollar) nicht eingeben, möglicherweise unerwartetes / nicht intuitives Verhalten auftritt (z. B. Matching). gestern "oder" warum ").

Durch das Setzen von Gruppierungszeichen "()" (Klammern) um die Optionen wird die Notwendigkeit verringert, für jede Option Anfangs- und Endezeichenfolgen zu setzen. Ohne sie kommt es möglicherweise zu unerwartetem Verhalten, wenn Sie mit Regex nicht vertraut sind. Wenn Sie keine Benutzereingaben verarbeiten, sondern eine Reihe bekannter Zeichenfolgen, ist diese natürlich besser lesbar, ohne dass Zeichenfolgen gruppiert und gestartet und beendet werden müssen.

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." } 
}
Takophiliac
quelle
-2

Der Schalter scheint in PowerShell 5.1 nicht zwischen Groß- und Kleinschreibung zu unterscheiden. Alle vier folgenden $someStringBeispiele funktionieren.

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

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

Hier sind meine $PSVersionTableDaten.

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
SmartieMcfly
quelle
1
Dies ist eine falsche Antwort. Richtig könnte sein wie folgt: $ a = 'b'; switch ($ a) {{$ _ -in 'a', 'b'} {'bingo'}; Standard {'nein!'}}
Mehrdad Mirreza
-4

Nachdem ich nach einer Lösung für dasselbe Problem wie Sie gesucht habe, habe ich dieses kleine Thema hier gefunden. Im Voraus habe ich eine viel reibungslosere Lösung für diesen Wechsel erhalten, case Statement

switch($someString) #switch is caseINsensitive, so you don't need to lower
{
    { 'y' -or 'yes' } { "You entered Yes." }
    default { "You entered No." }
}
Daniel
quelle
4
{'y' -oder 'yes'} wird immer als wahr ausgewertet, sodass der Standardzweig nie getroffen wird
Darren Gosbell