Vše, co jste kdy chtěli vědět o příkazu switch
- 03/01/2021
- 12 minut, aby si
-
- c
- x
stejně Jako mnoho jiných jazyků, PowerShell má příkazy pro řízení toku výkonu v yourscripts. Jedním z těchto tvrzení je příkaz switch a v PowerShell nabízí funkce, které se nenacházejí v jiných jazycích. Dnes se hluboce ponoříme do práce s PowerShellswitch
.
Poznámka:
původní verze tohoto článku vyšla na blogu napsal @KevinMarquette. Tým ThePowerShell děkuje Kevinovi za sdílení tohoto obsahu s námi. Prosím, podívejte se na jeho blog atPowerShellExplained.com.
if
Jeden z prvních příkazů, které se naučíte, je if
prohlášení. To vám umožní spustit skript blockif příkaz je $true
.
if ( Test-Path $Path ){ Remove-Item $Path}
můžete mít mnohem složitější logiku pomocí elseif
else
prohlášení. Zde je příklad, kde mám číselnou hodnotu pro den v týdnu a chci získat jméno jako řetězec.
$day = 3if ( $day -eq 0 ) { $result = 'Sunday' }elseif ( $day -eq 1 ) { $result = 'Monday' }elseif ( $day -eq 2 ) { $result = 'Tuesday' }elseif ( $day -eq 3 ) { $result = 'Wednesday' }elseif ( $day -eq 4 ) { $result = 'Thursday' }elseif ( $day -eq 5 ) { $result = 'Friday' }elseif ( $day -eq 6 ) { $result = 'Saturday' }$result
Wednesday
ukázalo se, že to je běžné vzor, a existuje mnoho způsobů, jak se s tím vypořádat. Jeden z nich je s switch
.
příkaz přepínače
příkazswitch
umožňuje zadat proměnnou a seznam možných hodnot. Pokud hodnotazrovnává proměnnou, provede se její scriptblock.
$day = 3switch ( $day ){ 0 { $result = 'Sunday' } 1 { $result = 'Monday' } 2 { $result = 'Tuesday' } 3 { $result = 'Wednesday' } 4 { $result = 'Thursday' } 5 { $result = 'Friday' } 6 { $result = 'Saturday' }}$result
'Wednesday'
Pro tento příklad, hodnota $day
odpovídá jedné číselné hodnoty, pak správné jméno isassigned $result
. V tomto příkladu provádíme pouze přiřazení proměnné, ale v těchto blocích skriptů lze provést libovolný PowerShell.
přiřadit proměnné
můžeme tento poslední příklad napsat jiným způsobem.
$result = switch ( $day ){ 0 { 'Sunday' } 1 { 'Monday' } 2 { 'Tuesday' } 3 { 'Wednesday' } 4 { 'Thursday' } 5 { 'Friday' } 6 { 'Saturday' }}
Jsme umístění hodnoty na PowerShell potrubí a přiřazením do $result
. Totéž můžete udělat s příkazy if
a foreach
.
výchozí
můžeme použítdefault
Klíčové slovo k identifikaci toho, co by se mělo stát, pokud neexistuje shoda.
$result = switch ( $day ){ 0 { 'Sunday' } # ... 6 { 'Saturday' } default { 'Unknown' }}
zde vracíme hodnotu Unknown
ve výchozím případě.
řetězce
v těchto posledních příkladech jsem porovnával čísla, ale můžete také porovnávat řetězce.
$item = 'Role'switch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role
rozhodl jsem se zabalit do Component
Role
Location
zápasy v uvozovkách zde upozornit, že jsou volitelné. switch
je ve většině případů považuje za řetězec.
pole
jednou z skvělých vlastností PowerShell switch
je způsob, jakým zpracovává pole. Pokud dáteswitch
pole, zpracovává každý prvek v této kolekci.
$roles = @('WEB','Database')switch ( $roles ) { 'Database' { 'Configure SQL' } 'WEB' { 'Configure IIS' } 'FileServer' { 'Configure Share' }}
Configure IISConfigure SQL
Pokud máte opakované položky v poli, pak jsou uzavřeno několikrát do příslušné části.
PSItem
můžete použít $PSItem
nebo $_
odkaz na aktuální položky, která byla zpracována. Když uděláme asimple match, $PSItem
je hodnota, kterou porovnáváme. Budu provádět některé pokročilé matchesin další části, kde je tato proměnná použita.
Parametry
jedinečný rys PowerShell switch
je, že to má řadu parametrů spínač, žezměna, jak se to provádí.
– CaseSensitive
zápasy nejsou ve výchozím nastavení velká a velká písmena. Pokud potřebujete rozlišovat velká a malá písmena, můžete použít-CaseSensitive
. To lze použít v kombinaci s dalšími parametry spínače.
– zástupný znak
můžeme povolit podporu zástupných znaků pomocí přepínače -wildcard
. Používá stejnou logiku zástupných znaků jako operátor-like
pro každou shodu.
$Message = 'Warning, out of disk space'switch -Wildcard ( $message ){ 'Error*' { Write-Error -Message $Message } 'Warning*' { Write-Warning -Message $Message } default { Write-Information $message }}
WARNING: Warning, out of disk space
Tady jsme zpracování zprávy a pak výstup na různé proudy založené na obsahu.
– Regex
příkaz switch podporuje regex zápasy, stejně jako to dělá zástupné znaky.
switch -Regex ( $message ){ '^Error' { Write-Error -Message $Message } '^Warning' { Write-Warning -Message $Message } default { Write-Information $message }}
mám více příkladů použití regulárního výrazu v jiném článku, který jsem napsal: mnoho způsobů použití regulárního výrazu.
– File
málo známou vlastností příkazu switch je, že dokáže zpracovat soubor s parametrem -File
. Použijete -file
s cestou k souboru místo toho, abyste mu dali proměnný výraz.
switch -Wildcard -File $path{ 'Error*' { Write-Error -Message $PSItem } 'Warning*' { Write-Warning -Message $PSItem } default { Write-Output $PSItem }}
funguje stejně jako zpracování pole. V tomto příkladu jej kombinuji s porovnáním zástupných znaků a použiji $PSItem
. To by proces log souboru, a převést ji na varování a chybové zprávy v závislosti na regex zápasy.
Rozšířené informace
Nyní, že jste si vědomi všech těchto zdokumentovaných funkcí, můžeme je použít v kontextu dalšípokročilý zpracování.
výrazy
switch
může být na výrazu místo proměnné.
switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}
bez ohledu na to, na co výraz vyhodnotí, je hodnota použitá pro shodu.
více zápasů
možná jste to již zachytili, ale switch
se může shodovat s více podmínkami. To platí zejména při použití -wildcard
nebo -regex
. Můžete přidat stejnou podmínku multipletimes a všechny z nich jsou spuštěny.
switch ( 'Word' ){ 'word' { 'lower case word match' } 'Word' { 'mixed case word match' } 'WORD' { 'upper case word match' }}
lower case word matchmixed case word matchupper case word match
všechny tři tyto příkazy jsou vypáleny. To ukazuje, že každá podmínka je kontrolována (v pořadí). To platí pro zpracování polí, kde každá položka kontroluje každou podmínku.
Pokračovat
za normálních okolností, to je místo, kde bych chtěl představit break
tvrzení, ale je to lepší, že jsme se naučit, jak používat continue
první. Stejně jako s foreach
smyčky, continue
pokračuje na další položku v kolekci nebo ukončí switch
pokud tam nejsou žádné další položky. Můžeme přepsat Poslední příklads pokračujícími příkazy tak, aby se spustil pouze jeden příkaz.
switch ( 'Word' ){ 'word' { 'lower case word match' continue } 'Word' { 'mixed case word match' continue } 'WORD' { 'upper case word match' continue }}
lower case word match
Místo odpovídající všechny tři položky, první z nich je uzavřeno a spínače pokračuje do nextvalue. Protože neexistují žádné hodnoty pro zpracování, přepínač ukončí. Tento další příklad ukazuje, jak by zástupný znak mohl odpovídat více položkám.
switch -Wildcard -File $path{ '*Error*' { Write-Error -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}
Protože přímka ve vstupní soubor by mohl obsahovat slovo Error
Warning
, chceme jen prvním spuštění a pak pokračovat ve zpracování souboru.
přerušení
abreak
příkaz ukončí přepínač. Toto je stejné chování, které continue
představuje pro singlevalues. Rozdíl je zobrazen při zpracování pole. break
zastaví veškeré zpracování v přepínačia continue
přesune na další položku.
$Messages = @( 'Downloading update' 'Ran into errors downloading file' 'Error: out of disk space' 'Sending email' '...')switch -Wildcard ($Messages){ 'Error*' { Write-Error -Message $PSItem break } '*Error*' { Write-Warning -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}
Downloading updateWARNING: Ran into errors downloading filewrite-error -message $PSItem : Error: out of disk space+ CategoryInfo : NotSpecified: (:) , WriteErrorException+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
V tomto případě, když narazíme na řádky, které začínají s Error
pak dostaneme chybu a spínač se zastaví.To je to, co pro nás dělá prohlášení break
. Pokud najdeme Error
uvnitř řetězce a nejen na začátku, zapíšeme to jako varování. Totéž děláme pro Warning
. Je možné, že řádek může mít jak slovo Error
, tak Warning
, ale potřebujeme pouze jeden proces. To je to, co pro nás dělá příkaz continue
.
Break štítky
switch
tvrzení podporuje break/continue
štítky stejně jako foreach
.
:filelist foreach($path in $logs){ :logFile switch -Wildcard -File $path { 'Error*' { Write-Error -Message $PSItem break filelist } 'Warning*' { Write-Error -Message $PSItem break logFile } default { Write-Output $PSItem } }}
osobně se mi nelíbí používání značek přerušení, ale chtěl jsem na ně poukázat, protože se zaměňují, pokud jste je nikdy předtím neviděli. Když máte více switch
nebo foreach
statementsthat jsou vnořené, možná budete chtít, aby se vymanily z více než vnitřní položkou. Můžete umístit štítek a switch
, který může být cílem vašeho break
.
Enum
PowerShell 5.0 nám dal ENUM a můžeme je použít v přepínači.
enum Context { Component Role Location}$item = ::Roleswitch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role
Pokud chcete zachovat vše jako silně zadané enumy, můžete je umístit do závorek.
switch ($item ){ (::Component) { 'is a component' } (::Role) { 'is a role' } (::Location) { 'is a location' }}
závorky jsou zde potřebné, tak, že přepínač není léčit hodnota ::Location
asa doslovný řetězec.
ScriptBlock
v případě potřeby můžeme použít scriptblock k provedení vyhodnocení shody.
$age = 37switch ( $age ){ {$PSItem -le 18} { 'child' } {$PSItem -gt 18} { 'adult' }}
'adult'
to přidává složitost a může vaše switch
těžko číst. Ve většině případů, kdy byste použiliněco takového by bylo lepší použítif
aelseif
příkazy. Uvažoval bych o použití tohoto, kdybych už měl velký přepínač na místě a potřeboval jsem dvě položky, abych zasáhl stejný hodnotící blok.
jedna věc, o které si myslím, že pomáhá s čitelností, je umístit scriptblock do závorek.
switch ( $age ){ ({$PSItem -le 18}) { 'child' } ({$PSItem -gt 18}) { 'adult' }}
stále provádí stejným způsobem a poskytuje lepší vizuální přestávku při rychlém pohledu na to.
Regex $ matches
musíme znovu použít regex, abychom se dotkli něčeho, co není okamžitě zřejmé. Použití regexpopuluje proměnnou $matches
. Jdu do použití $matches
více, když mluvím o mnoha způsobech použití regulárního výrazu. Zde je rychlý vzorek, který jej ukáže v akci s pojmenovanými zápasy.
$message = 'my ssn is 123-23-3456 and credit card: 1234-5678-1234-5678'switch -regex ($message){ '(?<SSN>\d\d\d-\d\d-\d\d\d\d)' { Write-Warning "message contains a SSN: $($matches.SSN)" } '(?<CC>\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d)' { Write-Warning "message contains a credit card number: $($matches.CC)" } '(?<Phone>\d\d\d-\d\d\d-\d\d\d\d)' { Write-Warning "message contains a phone number: $($matches.Phone)" }}
WARNING: message may contain a SSN: 123-23-3456WARNING: message may contain a credit card number: 1234-5678-1234-5678
$null
můžete odpovídat $null
hodnotu, která nemusí být výchozí.
$value = $nullswitch ( $value ){ $null { 'Value is null' } default { 'value is not null' }}```OutputValue is null
totéž platí pro prázdný řetězec.
switch ( '' ){ '' { 'Value is empty' } default { 'value is a empty string' }}```OutputValue is empty
Konstantní výraz
značka Lee Dailey poukázal na to, že můžeme použít konstantní $true
vyjádření k vyhodnocení položky.Představte si, že máme několik booleovských kontrol, které se musí stát.
$isVisible = $false$isEnabled = $true$isSecure = $trueswitch ( $true ){ $isEnabled { 'Do-Action' } $isVisible { 'Show-Animation' } $isSecure { 'Enable-AdminMenu' }}
Do-ActionEnabled-AdminMenu
Jedná se o čistý způsob, jak vyhodnotit a podniknout kroky na stav několika booleovských polí. Skvělá věc na tom je, že můžete mít jeden zápas otočit stav hodnoty, která ještě nebyla vyhodnocena.
$isVisible = $false$isEnabled = $true$isAdmin = $falseswitch ( $true ){ $isEnabled { 'Do-Action' $isVisible = $true } $isVisible { 'Show-Animation' } $isAdmin { 'Enable-AdminMenu' }}
Do-ActionShow-Animation
Nastavení $isEnabled
$true
v tomto příkladu je si jistý, že $isVisible
je také nastaven na$true
. Poté, když je $isVisible
vyhodnocen, je vyvolán jeho scriptblock. Toto je bitcounter-intuitivní, ale je to chytré použití mechaniky.
$spínač automatické proměnné
Když switch
je zpracování své hodnoty, vytváří výčtu a volání $switch
. Jedná se o automatickou proměnnou vytvořenou PowerShell a můžete s ní přímo manipulovat.
$a = 1, 2, 3, 4switch($a) { 1 { $switch.MoveNext(); $switch.Current } 3 { $switch.MoveNext(); $switch.Current }}
To vám dává výsledky:
24
pohybem enumerator dopředu, další položka nemá zpracovány switch
, ale může dostat přístup ke hodnotu přímo. Nazval bych to šílenstvím.
další vzory
Hashtables
jeden z mých nejoblíbenějších příspěvků je ten, který jsem udělal na hashtagech. Jedním z případů použitíhashtable
je vyhledávací tabulka. To je alternativní přístup k společný vzor, kterýswitch
prohlášení je často řešení.
$day = 3$lookup = @{ 0 = 'Sunday' 1 = 'Monday' 2 = 'Tuesday' 3 = 'Wednesday' 4 = 'Thursday' 5 = 'Friday' 6 = 'Saturday'}$lookup
Wednesday
Pokud jsem jen pomocí switch
jako vyhledávání, často jsem použít hashtable
místo.
Enum
PowerShell 5.0 představil Enum
a je to také možnost v tomto případě.
$day = 3enum DayOfTheWeek { Sunday Monday Tuesday Wednesday Thursday Friday Saturday}$day
Wednesday
mohli bychom celý den hledat různé způsoby řešení tohoto problému. Jen jsem se chtěl ujistit, že víš, že máš možnosti.
závěrečná slova
příkaz switch je na povrchu jednoduchý, ale nabízí některé pokročilé funkce, které si většina lidí neuvědomuje, že jsou k dispozici. Navlékání těchto funkcí dohromady činí tuto výkonnou funkci. Doufám, že ses naučil něco, co sis předtím neuvědomil.