Udostępnij za pośrednictwem


o_przełączniku

Krótki opis

W tym artykule wyjaśniono, jak używać przełącznika do obsługi wielu instrukcji warunkowych.

Długi opis

Aby sprawdzić warunek w skry skrycie lub funkcji, możesz użyć instrukcji if . Instrukcja if może sprawdzać wiele typów warunków, w tym wartość zmiennych i właściwości obiektów.

Aby sprawdzić wiele warunków, możesz użyć instrukcji switch . Instrukcja switch jest podobna do serii instrukcji if , ale jest prostsza. Instrukcja switch zawiera listę każdego warunku i odpowiednią akcję. Jeśli warunek jest zgodny, wykonywana jest akcja.

Ważne

Instrukcja switch konwertuje wszystkie wartości na ciągi przed porównaniem.

Składnia

Podstawowa switch instrukcja ma następujący format:

switch (<test-expression>) {
    <result1-to-be-matched> {<action>}
    <result2-to-be-matched> {<action>}
}

Składnia instrukcji switch jest podobna do następujących if instrukcji:

if ("$(<result1-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}
if ("$(<result2-to-be-matched>)") -eq ("$(<test-expression>)") {<action>}

Wyrażenia obejmują wartości literału (ciągi lub liczby), zmienne i bloki skryptów, które zwracają wartość logiczną. Instrukcja switch konwertuje wszystkie wartości na ciągi przed porównaniem. Aby zapoznać się z przykładem, zobacz Wpływ konwersji ciągów w dalszej części tego artykułu.

Element jest obliczany <test-expression> w trybie wyrażenia. Jeśli wyrażenie zwraca więcej niż jedną wartość, taką jak tablica lub inny typ wyliczalny, switch instrukcja oblicza każdą wyliczonej wartości oddzielnie.

Wyrażenie <result-to-be-matched> jest wyrażeniem musi być rozpoznawane jako pojedyncza wartość. Ta wartość jest porównywana z wartością wejściową.

Wartość default jest zarezerwowana dla akcji używanej, gdy nie ma innych dopasowań.

Instrukcja switch może używać zmiennych automatycznych $_ i $switch . Zmienna automatyczna zawiera wartość wyrażenia przekazanego do switch instrukcji i jest dostępna do oceny i użycia w zakresie instrukcji <result-to-be-matched> . Aby uzyskać więcej informacji, zobacz about_Automatic_Variables.

switch Pełna składnia instrukcji jest następująca:

switch [-Regex | -Wildcard | -Exact] [-CaseSensitive] (<test-expression>) {
    string | number | variable | { <value-scriptblock> }
        { <action-scriptblock> }
    default { <action-scriptblock> } # optional
}

lub

switch [-Regex | -Wildcard | -Exact] [-CaseSensitive] -File filename {
    string | number | variable | { <value-scriptblock> }
        { <action-scriptblock> }
    default { <action-scriptblock> }  # optional
}

Jeśli nie używasz parametrów, switch zachowuje się tak samo jak przy użyciu parametru Exact. Wykonuje dopasowanie bez uwzględniania wielkości liter dla wartości. Jeśli wartość jest kolekcją, każdy element jest obliczany w kolejności, w jakiej się pojawia.

Instrukcja switch musi zawierać co najmniej jedną instrukcję warunku.

Klauzula default jest wyzwalana, gdy wartość nie pasuje do żadnego z warunków. Jest ona równoważna klauzuli else w instrukcji if. Tylko jedna default klauzula jest dozwolona w każdej switch instrukcji.

switch ma następujące parametry:

  • Symbol wieloznaczny — wskazuje, że warunek jest ciągiem wieloznacznymi . Jeśli klauzula match nie jest ciągiem, parametr jest ignorowany. Porównanie jest bez uwzględniania wielkości liter.
  • Exact — wskazuje, że klauzula match, jeśli jest to ciąg, musi być dokładnie zgodna. Jeśli klauzula match nie jest ciągiem, ten parametr jest ignorowany. Porównanie jest bez uwzględniania wielkości liter.
  • CaseSensitive — wykonuje dopasowanie uwzględniające wielkość liter. Jeśli klauzula match nie jest ciągiem, ten parametr jest ignorowany.
  • plik — pobiera dane wejściowe z pliku, a nie <test-expression>. Plik jest odczytywany w danym momencie i oceniany przez instrukcję switch. Domyślnie porównanie jest niewrażliwe na wielkość liter. Parametr plik obsługuje tylko jeden plik. Jeśli uwzględniono wiele parametrów pliku , zostanie użyty tylko ostatni. Aby uzyskać więcej informacji, zobacz Przykłady parametrów pliku.
  • Regex — wykonuje wyrażenie regularne pasujące do wartości warunku. Jeśli klauzula match nie jest ciągiem, ten parametr jest ignorowany. Porównanie jest bez uwzględniania wielkości liter. Zmienna automatyczna $Matches jest dostępna do użycia w bloku zgodnej instrukcji.

Uwaga

Podczas określania wartości powodujących konflikt, takich jak Regex i Symbol wieloznaczny, ostatni określony parametr ma pierwszeństwo, a wszystkie parametry powodujące konflikt są ignorowane. Dozwolone jest również wiele wystąpień parametrów. Jest jednak używany tylko ostatni parametr wymieniony.

Przykłady

W poniższych przykładach pokazano użycie instrukcji switch .

Proste przykłady dopasowania

W poniższym przykładzie instrukcja switch porównuje wartość testu 3 z każdym z warunków. Gdy wartość testu jest zgodna z warunkiem, wykonywana jest akcja.

switch (3) {
    1 { "It's one."   }
    2 { "It's two."   }
    3 { "It's three." }
    4 { "It's four."  }
}
It's three.

W tym przykładzie wartość jest porównywana z każdym warunkiem na liście. Poniższa instrukcja switch ma dwa warunki dla wartości 3, co pokazuje, że wszystkie warunki są testowane.

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.

Używanie break i continue sterowanie przepływem

Jeśli wartość jest zgodna z wieloma warunkami, wykonywana jest akcja dla każdego warunku. Aby zmienić to zachowanie, użyj break słów kluczowych lub continue .

Słowo break kluczowe zatrzymuje przetwarzanie i zamyka instrukcję switch .

Słowo continue kluczowe zatrzymuje przetwarzanie bieżącej wartości, ale kontynuuje przetwarzanie wszystkich kolejnych wartości.

Poniższy przykład przetwarza tablicę liczb i wyświetla, czy są dziwne, czy nawet. Liczby ujemne są pomijane za pomocą słowa kluczowego continue . Jeśli napotkano nieliczebną liczbę, wykonanie zostanie zakończone za pomocą słowa kluczowego 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

Wpływ konwersji ciągów

Wszystkie wartości, zarówno dane wejściowe, jak i wartość porównania są konwertowane na ciągi do porównania. Aby uniknąć niezamierzonej konwersji ciągów, użyj bloków skryptów, aby ocenić wartość przełącznika.

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

Właściwość DayOfWeek obiektu date jest wyliczeniem. Podczas gdy wyliczenia mogą być porównywane z wartościami liczbowymi lub ciągami, switch instrukcja konwertuje wartość na ciąg reprezentujący wyliczenie.

The string value matches a Thursday.
The expression matches a Thursday.

To zachowanie różni się od zachowania -eq porównania w instrukcji if .

if (4 -eq ([datetime]'1 Jan 1970').DayOfWeek) {
    'The integer value matches a Thursday.'
}
The value matches a Thursday.

W tym przykładzie tabela skrótów jest przekazywana do instrukcji switch . Element switch konwertuje tabelę skrótu na ciąg.

$test = @{
    Test  = 'test'
    Test2 = 'test2'
}

$test.ToString()
System.Collections.Hashtable

Zwróć uwagę, że reprezentacja ciągu tabeli skrótu nie jest taka sama jak wartość klucza testowego .

switch -Exact ($test) {
    'System.Collections.Hashtable' { 'Hashtable string coercion' }
    'test'                         { 'Hashtable value' }
}
Hashtable string coercion

Użyj switch polecenia , aby przetestować wartości w tabeli skrótów

W tym przykładzie instrukcja switch testuje typ wartości w tabeli skrótu. Zanim będziemy mogli przetestować wartości, musimy wyliczyć elementy w tabeli skrótów. Aby uniknąć komplikacji konwersji ciągów, użyj bloku skryptu, który zwraca wartość logiczną, aby wybrać blok skryptu akcji do wykonania.

$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

Używanie symboli wieloznacznych z switch

W tym przykładzie nie ma pasującego przypadku, więc nie ma żadnych danych wyjściowych.

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

Dodając klauzulę default , można wykonać akcję, gdy żadne inne warunki nie powiedzie się.

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

Aby wyraz fourteen był zgodny z przypadkiem, należy użyć parametru -Wildcard lub -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.

Używanie wyrażeń regularnych z switch

W poniższym przykładzie użyto parametru -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

W poniższym przykładzie pokazano użycie bloków skryptu jako switch warunków instrukcji.

switch ("Test") {
    { $_ -is [string] } { "Found a string" }
    "Test"              { "This $_ executes as well" }
}
Found a string
This Test executes as well

Poniższy przykład przetwarza tablicę zawierającą dwie wartości daty. Właściwość <value-scriptblock> Year porównuje właściwość Year każdej daty. Zostanie <action-scriptblock> wyświetlony komunikat powitalny lub liczba dni do początku roku 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!' }
}

Odczytywanie zawartości pliku za pomocą polecenia switch

Użycie instrukcji switch z parametrem file jest wydajnym sposobem przetwarzania wierszy dużych plików według wiersza. Program PowerShell przesyła strumieniowo wiersze pliku do instrukcji switch. Każdy wiersz jest przetwarzany indywidualnie.

Przetwarzanie można zakończyć przed osiągnięciem końca pliku przy użyciu słowa kluczowego break w instrukcji action. Instrukcja switch jest wydajniejsza niż używanie Get-Content do przetwarzania dużych plików wiersz po wierszu.

Można połączyć switch -File z -Wildcard lub -Regex w celu elastycznego i wydajnego dopasowywania wzorców liniowych.

Poniższy przykład odczytuje README.md w repozytorium PowerShell-Docs. Zwraca on dane wyjściowe każdego wiersza, dopóki nie osiągnie wiersza rozpoczynającego się od ##.

switch -Regex -File .\README.md {
    '^##\s' { break }
    default { $_; continue }
}

<filename> Argument akceptuje wyrażenia wieloznaczne, ale musi być zgodny tylko z jednym plikiem. Poniższy przykład jest taki sam jak poprzedni, z wyjątkiem użycia symbolu wieloznakowego w argumencie <filename>. Ten przykład działa, ponieważ wzorzec wieloznaczny pasuje tylko do jednego pliku.

switch -Regex -File .\README.* {
    '^##\s' { break }
    default { $_; continue }
}

Należy użyć znaków ucieczki, które mogą być interpretowane jako symbole wieloznaczne, jeśli chcesz, aby były traktowane jako literały.

$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

Zobacz też