Articles

allt du någonsin velat veta om switch uttalande

  • 03/01/2021
  • 12 minuter att läsa
    • s
    • c
    • X

liksom många andra språk har PowerShell kommandon för att styra flödet av körning inom yourscripts. Ett av dessa uttalanden är switch-uttalandet och i PowerShell erbjuder det funktioner som inte finns på andra språk. Idag tar vi ett djupt dyk i att arbeta med PowerShellswitch.

Obs

den ursprungliga versionen av denna artikel dök upp på bloggen skriven av @KevinMarquette. ThePowerShell team tack Kevin för att dela detta innehåll med oss. Vänligen kolla in hans blogg atPowerShellExplained.com.

if-uttalandet

en av de första uttalandena som du lär dig ärif – uttalandet. Det låter dig köra ett skriptblock om ett uttalande är $true.

if ( Test-Path $Path ){ Remove-Item $Path}

Du kan ha mycket mer komplicerad logik genom att använda elseifoch else uttalanden. Här är ett exempeldär jag har ett numeriskt värde för veckodag och jag vill få namnet som en sträng.

$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

det visar sig att detta är ett vanligt mönster och det finns många sätt att hantera detta. Oneof dem är med en switch.

Switch statement

switch – satsen låter dig ange en variabel och en lista över möjliga värden. Om värdetmatchar variabeln, körs dess 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'

för detta exempel matchar värdet på $dayett av de numeriska värdena, då är det korrekta namnet tilldelat $result. Vi gör bara en variabel uppgift i det här exemplet, men alla PowerShell kan utföras i dessa skriptblock.

tilldela en variabel

Vi kan skriva det sista exemplet på ett annat sätt.

$result = switch ( $day ){ 0 { 'Sunday' } 1 { 'Monday' } 2 { 'Tuesday' } 3 { 'Wednesday' } 4 { 'Thursday' } 5 { 'Friday' } 6 { 'Saturday' }}

vi placerar värdet på PowerShell-rörledningen och tilldelar det till $result. Du kan göraDetta samma sak medif ochforeach uttalanden.

standard

Vi kan använda default för att identifiera vad som ska hända om det inte finns någon matchning.

$result = switch ( $day ){ 0 { 'Sunday' } # ... 6 { 'Saturday' } default { 'Unknown' }}

här returnerar vi värdet Unknown I standardfallet.

strängar

jag matchade siffror i de sista exemplen, men du kan också matcha strängar.

$item = 'Role'switch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role

jag bestämde mig för att inte sätta in ComponentRole och Location matchar i citat här för att markera detde är valfria. switch behandlar dem som en sträng i de flesta fall.

Arrays

en av de coola funktionerna i PowerShellswitch är hur den hanterar arrays. Om du ger enswitch en array, bearbetar den varje element i den samlingen.

$roles = @('WEB','Database')switch ( $roles ) { 'Database' { 'Configure SQL' } 'WEB' { 'Configure IIS' } 'FileServer' { 'Configure Share' }}
Configure IISConfigure SQL

Om du har upprepade objekt i din array matchas de flera gånger av lämpligt avsnitt.

PSItem

Du kan använda $PSItem eller $_ för att referera till det aktuella objektet som behandlades. När vi gör en enkel matchning är$PSItem det värde som vi matchar. Jag kommer att utföra några avancerade matchesi nästa avsnitt där denna variabel används.

parametrar

en unik egenskap hos PowerShell switch är att den har ett antal omkopplarparametrar somändra hur det fungerar.

-CaseSensitive

matchningarna är inte skiftlägeskänsliga som standard. Om du behöver vara skiftlägeskänslig kan du använda-CaseSensitive. Detta kan användas i kombination med de andra omkopplarparametrarna.

-jokertecken

Vi kan aktivera jokerstöd med-wildcard switch. Detta använder samma jokertecken logik som-like operatör för att göra varje match.

$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

här bearbetar vi ett meddelande och matar sedan ut det på olika strömmar baserat på innehållet.

-Regex

switch-uttalandet stöder regex-matchningar precis som det gör jokertecken.

switch -Regex ( $message ){ '^Error' { Write-Error -Message $Message } '^Warning' { Write-Warning -Message $Message } default { Write-Information $message }}

Jag har fler exempel på att använda regex i en annan artikel Jag skrev: de många sätten att använda regex.

-File

en lite känd funktion i switch-uttalandet är att den kan bearbeta en fil med parametern -File. Du använder -file med en sökväg till en fil istället för att ge den ett variabelt uttryck.

switch -Wildcard -File $path{ 'Error*' { Write-Error -Message $PSItem } 'Warning*' { Write-Warning -Message $PSItem } default { Write-Output $PSItem }}

det fungerar precis som att bearbeta en array. I det här exemplet kombinerar jag det med jokerteckenmatchning ochanvänd $PSItem. Detta skulle bearbeta en loggfil och konvertera den till varning och felmeddelanden beroende på regex-matchningarna.

avancerade detaljer

Nu när du är medveten om alla dessa dokumenterade funktioner kan vi använda dem i samband med meravancerad bearbetning.

uttryck

switch kan vara på ett uttryck istället för en variabel.

switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}

vad uttrycket utvärderar till är det värde som används för matchningen.

flera matchningar

Du kanske redan har plockat upp detta, men ett switch kan matcha flera villkor. Detta är särskilt sant när du använder-wildcard eller-regex matchar. Du kan lägga till samma villkor multipletimes och alla av dem utlöses.

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

alla tre av dessa uttalanden avfyras. Detta visar att varje villkor kontrolleras (i ordning). Thisholds sant för bearbetning arrays där varje objekt kontrollerar varje villkor.

Fortsätt

normalt är det här jag skulle introducerabreak uttalande, men det är bättre att vi lär oss huratt användacontinue först. Precis som med en foreach loop, continue fortsätter till nästa punkt i samlingen eller avslutar switch om det inte finns fler objekt. Vi kan skriva om det sista exempeletmed fortsätt uttalanden så att endast ett uttalande körs.

switch ( 'Word' ){ 'word' { 'lower case word match' continue } 'Word' { 'mixed case word match' continue } 'WORD' { 'upper case word match' continue }}
lower case word match

istället för att matcha alla tre objekten matchas den första och omkopplaren fortsätter till nästa värde. Eftersom det inte finns några värden kvar att bearbeta, går omkopplaren ut. Detta nästa exempel visarhur ett jokertecken kan matcha flera objekt.

switch -Wildcard -File $path{ '*Error*' { Write-Error -Message $PSItem continue } '*Warning*' { Write-Warning -Message $PSItem continue } default { Write-Output $PSItem }}

eftersom en rad i inmatningsfilen kan innehålla både ordet Erroroch Warning, vill vi bara att den första ska köras och sedan fortsätta bearbeta filen.

Break

A break uttalande lämnar omkopplaren. Detta är samma beteende somcontinue presenterar för singlevalues. Skillnaden visas vid bearbetning av en matris. break stoppar all bearbetning i omkopplaren ochcontinue flyttas till nästa objekt.

$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

i det här fallet, om vi träffar några rader som börjar med Error då får vi ett fel och omkopplaren stannar.Detta är vad detbreak uttalande gör för oss. Om vi hittar Error inuti strängen och intebara i början skriver vi det som en varning. Vi gör samma sak för Warning. Det är möjligt att en rad kan ha både ordet Erroroch Warning, men vi behöver bara en toprocess. Detta är vadcontinue uttalande gör för oss.

Break etiketter

switch uttalande stöderbreak/continue etiketter precis somforeach.

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

Jag gillar personligen inte användningen av brytetiketter men jag ville påpeka dem eftersom de ’ reconfusing om du aldrig har sett dem tidigare. När du har fleraswitch ellerforeach uttalandensom är kapslade kanske du vill bryta ut mer än det inre mest objektet. Du kan placera en labelon a switch som kan vara målet för ditt break.

Enum

PowerShell 5.0 gav oss enums och vi kan använda dem i en switch.

enum Context { Component Role Location}$item = ::Roleswitch ( $item ){ Component { 'is a component' } Role { 'is a role' } Location { 'is a location' }}
is a role

Om du vill behålla allt så starkt skrivna enums kan du placera dem inom parentes.

switch ($item ){ (::Component) { 'is a component' } (::Role) { 'is a role' } (::Location) { 'is a location' }}

parenteserna behövs här så att omkopplaren inte behandlar värdet::Location Asa bokstavlig sträng.

ScriptBlock

Vi kan använda ett scriptblock för att utföra utvärderingen för en matchning om det behövs.

$age = 37switch ( $age ){ {$PSItem -le 18} { 'child' } {$PSItem -gt 18} { 'adult' }}
'adult'

detta lägger till komplexitet och kan göra ditt switch svårt att läsa. I de flesta fall där du skulle användanågot så här skulle det vara bättre att använda if och elseif uttalanden. Jag skulle överväga att använda detta om jag redan hade en stor omkopplare på plats och jag behövde två saker för att träffa samma utvärderingsblock.

en sak som jag tror hjälper till med läsbarhet är att placera scriptblock inom parentes.

switch ( $age ){ ({$PSItem -le 18}) { 'child' } ({$PSItem -gt 18}) { 'adult' }}

det körs fortfarande på samma sätt och ger en bättre visuell paus när man snabbt tittar på den.

Regex $matchar

Vi måste återkomma regex för att beröra något som inte är omedelbart uppenbart. Användningen av regexpopulates$matches variabel. Jag går in i användningen av $matches mer när jag pratar omde många sätten att använda regex. Här är ett snabbt prov för att visa det i aktion med namngivna matchningar.

$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

Du kan matcha ett $null värde som inte behöver vara standard.

$value = $nullswitch ( $value ){ $null { 'Value is null' } default { 'value is not null' }}```OutputValue is null

samma gäller för en tom sträng.

switch ( '' ){ '' { 'Value is empty' } default { 'value is a empty string' }}```OutputValue is empty

konstant uttryck

Lee Dailey påpekade att vi kan använda en konstant $trueuttryck för att utvärdera objekt.Tänk om vi har flera booleska kontroller som måste hända.

$isVisible = $false$isEnabled = $true$isSecure = $trueswitch ( $true ){ $isEnabled { 'Do-Action' } $isVisible { 'Show-Animation' } $isSecure { 'Enable-AdminMenu' }}
Do-ActionEnabled-AdminMenu

detta är ett rent sätt att utvärdera och vidta åtgärder för status för flera booleska fält. Thecool sak om detta är att du kan ha en match vända status för ett värde som inte har utvärderats ännu.

$isVisible = $false$isEnabled = $true$isAdmin = $falseswitch ( $true ){ $isEnabled { 'Do-Action' $isVisible = $true } $isVisible { 'Show-Animation' } $isAdmin { 'Enable-AdminMenu' }}
Do-ActionShow-Animation

inställning $isEnabled till $true I det här exemplet ser du till att $isVisible också är inställt på$true. Sedan när $isVisible utvärderas, anropas dess scriptblock. Detta är en bitcounter-intuitivt men är en smart användning av mekaniken.

$switch automatisk variabel

närswitch bearbetar dess värden skapar den en uppräkare och kallar den$switch. Detta är en automatisk variabel skapad av PowerShell och du kan manipulera den direkt.

$a = 1, 2, 3, 4switch($a) { 1 { $switch.MoveNext(); $switch.Current } 3 { $switch.MoveNext(); $switch.Current }}

detta ger dig resultaten av:

24

genom att flytta uppräknaren framåt behandlas nästa objekt inte av switch men du kanåtgång till det värdet direkt. Jag skulle kalla det galenskap.

andra mönster

Hashtables

ett av mina mest populära inlägg är det jag gjorde på hashtables. Ett av användningsfallen för etthashtable är att vara en uppslagstabell. Det är ett alternativt tillvägagångssätt för ett gemensamt mönster som ettswitch – uttalande ofta adresserar.

$day = 3$lookup = @{ 0 = 'Sunday' 1 = 'Monday' 2 = 'Tuesday' 3 = 'Wednesday' 4 = 'Thursday' 5 = 'Friday' 6 = 'Saturday'}$lookup
Wednesday

Om jag bara använder ett switch som en sökning använder jag ofta ett hashtable istället.

Enum

PowerShell 5.0 introducerade Enum och det är också ett alternativ i det här fallet.

$day = 3enum DayOfTheWeek { Sunday Monday Tuesday Wednesday Thursday Friday Saturday}$day
Wednesday

Vi kan gå hela dagen och titta på olika sätt att lösa detta problem. Jag ville bara se till att du visste att du hade alternativ.

sista ord

omkopplingsuttalandet är enkelt på ytan men det erbjuder några avancerade funktioner som de flesta människor inte inser är tillgängliga. Att stränga dessa funktioner tillsammans gör detta till en kraftfull funktion. Jag hoppas att du lärde dig något som du inte hade insett tidigare.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *