Articles

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í elseifelse 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 ComponentRoleLocation 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 ErrorWarning, 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.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *