Articles

Alles wat u ooit wilde weten over het switch statement

  • 03/01/2021
  • 12 minuten te lezen
    • s
    • c
    • x

net Als veel andere talen, PowerShell commando ‘ s voor het controleren van de stroom van de uitvoering binnen yourscripts. Een van die statements is de switch statement en in PowerShell, het biedt featuresdie niet worden gevonden in andere talen. Vandaag nemen we een diepe duik in het werken met de PowerShellswitch.

Note

De originele versie van dit artikel verscheen op de blog geschreven door @KevinMarquette. Het PowerShell team bedankt Kevin voor het delen van deze content met ons. Bekijk zijn blog atPowerShellExplained.com.

het if statement

een van de eerste statements die u leert is het if statement. Hiermee kunt u een scriptblock uitvoeren als een statement $trueis.

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

u kunt veel ingewikkelder logica hebben door elseif en else statements te gebruiken. Hier is een voorbeeld waar ik een numerieke waarde heb voor de dag van de week en Ik wil de naam als een tekenreeks krijgen.

$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

het blijkt dat dit een algemeen patroon is en er zijn vele manieren om hiermee om te gaan. Eén ervan heeft een switch.

Switch statement

met het switch statement kunt u een variabele en een lijst met mogelijke waarden opgeven. Als de valuematches de variabele, dan is zijn scriptblock wordt uitgevoerd.

$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'

in dit voorbeeld komt de waarde van $day overeen met een van de numerieke waarden, waarna de juiste naam wordt toegewezen aan $result. We doen alleen een variabele toewijzing in dit voorbeeld, maar elke PowerShell kan worden uitgevoerd in die scriptblokken.

toewijzen aan een variabele

We kunnen dat laatste voorbeeld op een andere manier schrijven.

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

we plaatsen de waarde op de PowerShell-pijplijn en toewijzen deze aan de $result. U kunt hetzelfde doen met deif enforeach statements.

Default

we kunnen het default sleutelwoord gebruiken om te bepalen wat er moet gebeuren als er geen overeenkomst is.

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

Hier retourneren we de waarde Unknown in het standaard geval.

Strings

Ik kwam overeen met getallen in die laatste voorbeelden, maar u kunt ook overeenkomen met strings.

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

Ik heb besloten om de ComponentRole en Location niet af te wikkelen.dat ze optioneel zijn. De switch behandelt deze in de meeste gevallen als een string.

Arrays

een van de coole eigenschappen van de PowerShell switch is de manier waarop het arrays behandelt. Als je eenswitch een array geeft, verwerkt het elk element in die verzameling.

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

Als u herhaalde items in uw array hebt, dan worden ze meerdere keren gematcht door de aangewezen sectie.

PSItem

u kunt de $PSItem of $_ gebruiken om te verwijzen naar het huidige item dat werd verwerkt. Als we een eenvoudige Overeenkomst doen, is $PSItem de waarde die we overeenkomen. Ik zal wat geavanceerde matches uitvoeren in de volgende sectie waar deze variabele wordt gebruikt.

Parameters

een uniek kenmerk van de PowerShell switch is dat het een aantal schakelparameters heeft die veranderen hoe het presteert.

– hoofdlettergevoelig

de overeenkomsten zijn standaard niet hoofdlettergevoelig. Als u hoofdlettergevoelig moet zijn, kunt u-CaseSensitivegebruiken. Dit kan gebruikt worden in combinatie met de andere schakelparameters.

-Wildcard

We kunnen ondersteuning voor wildcard inschakelen met de -wildcard switch. Dit gebruikt dezelfde jokertekens als de-like operator om elke overeenkomst uit te voeren.

$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

Hier verwerken we een bericht en voeren het uit op verschillende streams gebaseerd op de inhoud.

– Regex

Het switch statement ondersteunt regex-overeenkomsten net als jokertekens.

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

Ik heb meer voorbeelden van het gebruik van regex in een ander artikel dat ik schreef: de vele manieren om regex te gebruiken.

-bestand

een weinig bekende eigenschap van het switch statement is dat het een bestand kan verwerken met de -Fileparameter. U gebruikt -file met een pad naar een bestand in plaats van het een variabele expressie te geven.

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

Het werkt net als het verwerken van een array. In dit voorbeeld combineer ik het met jokertekens en gebruik de $PSItem. Dit zou een logbestand verwerken en converteren naar waarschuwing en errormessages afhankelijk van de Regex wedstrijden.

geavanceerde details

Nu u op de hoogte bent van al deze gedocumenteerde functies, kunnen we ze gebruiken in de context van meer geavanceerde verwerking.

expressies

de switch kan op een expressie staan in plaats van op een variabele.

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

waar de expressie ook naar evalueert is de waarde die gebruikt wordt voor de overeenkomst.

meerdere overeenkomsten

u hebt dit misschien al opgepikt, maar een switch kan aan meerdere voorwaarden voldoen. Dit is met name waar wanneer -wildcard of -regex overeenkomt. U kunt dezelfde voorwaarde meerdere keren toevoegen en ze worden allemaal geactiveerd.

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

alle drie deze verklaringen worden afgevuurd. Dit toont aan dat elke conditie wordt gecontroleerd (in volgorde). Dit geldt voor het verwerken van arrays waar elk item elke voorwaarde controleert.

Doorgaan

normaal gesproken zou ik hier het break statement introduceren, maar het is beter dat we eerst leren hoe we continue kunnen gebruiken. Net als bij een lus foreach, gaat continue verder naar het volgende item in de collectie of verlaat de switch als er geen items Meer zijn. We kunnen dat laatste voorbeeld herschrijven met continue statements zodat er maar één statement wordt uitgevoerd.

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

in plaats van alle drie de items te matchen, wordt de eerste gevonden en gaat de schakelaar door naar de volgende waarde. Omdat er geen waarden meer te verwerken zijn, verlaat de schakelaar. In het volgende voorbeeld wordt getoond hoe een jokerteken kan overeenkomen met meerdere items.

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

omdat een regel in het invoerbestand zowel het woord Error en Warning kan bevatten, willen we alleen dat de eerste het bestand uitvoert en vervolgens verder verwerkt.

Break

abreak statement verlaat de schakelaar. Dit is hetzelfde gedrag dat continue presenteert voor singlevalues. Het verschil wordt weergegeven bij het verwerken van een array. break stopt alle verwerking in de switch en continue gaat naar het volgende item.

$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

in dit geval krijgen we een fout en stopt de schakelaar.Dit is wat dat break statement voor ons doet. Als we Error in de string vinden en niet alleen aan het begin, schrijven we het als een waarschuwing. We doen hetzelfde voor Warning. Het is mogelijk dat een regel zowel het woord Error en Warning zou kunnen hebben, maar we hebben er maar één nodig om te verwerken. Dit is wat het continue statement voor ons doet.

Break labels

het switch statement ondersteunt break/continue labels net als 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 } }}

persoonlijk hou ik niet van het gebruik van break labels, maar ik wilde ze wijzen omdat ze niet gebruiken als je ze nog nooit eerder hebt gezien. Wanneer u meerdereswitch offoreach statements hebt die genest zijn, wilt u misschien meer dan het binnenste most item doorbreken. U kunt een label A switch plaatsen dat het doel kan zijn van uw break.

Enum

PowerShell 5.0 gaf ons enums en we kunnen ze gebruiken in een switch.

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

Als u alles als sterk getypte enums wilt behouden, kunt u ze tussen haakjes plaatsen.

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

de haakjes zijn hier nodig zodat de switch de waarde ::Location niet als letterlijke tekenreeks behandelt.

ScriptBlock

We kunnen een scriptblock gebruiken om de evaluatie uit te voeren voor een overeenkomst indien nodig.

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

Dit voegt complexiteit toe en kan uw switch moeilijk te lezen maken. In de meeste gevallen waar u iets als dit zou gebruiken, zou het beter zijn om if en elseif statements te gebruiken. Ik zou overwegen om dit te gebruiken als ik al een grote schakelaar had en ik twee items nodig had om hetzelfde evaluatieblok te raken.

een ding dat volgens mij helpt bij de leesbaarheid is om het scriptblok tussen haakjes te plaatsen.

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

Het voert nog steeds op dezelfde manier uit en geeft een betere visuele pauze als je er snel naar kijkt.

Regex $matches

We moeten regex opnieuw bezoeken om iets aan te raken dat niet meteen duidelijk is. Het gebruik van regexpopuleert de variabele $matches. Ik ga meer in op het gebruik van $matches wanneer ik praat over de vele manieren om regex te gebruiken. Hier is een snel voorbeeld om het in actie te laten zien met named matches.

$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

u kunt overeenkomen met een $null waarde die niet de standaard hoeft te zijn.

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

hetzelfde geldt voor een lege tekenreeks.

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

constante expressie

Lee Dailey wees erop dat we een constante$true expressie kunnen gebruiken om items te evalueren.Stel je voor dat we meerdere Booleaanse controles hebben die moeten gebeuren.

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

Dit is een schone manier om de status van verschillende Booleaanse velden te evalueren en actie te ondernemen. Het leuke hieraan is dat je één match de status van een waarde kunt laten omdraaien die nog niet is geëvalueerd.

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

instelling $isEnabled to $true in dit voorbeeld zorgt ervoor dat $isVisible ook is ingesteld op$true. Wanneer $isVisible wordt geëvalueerd, wordt het scriptblok aangeroepen. Dit is een bitcounter-intuïtief, maar is een slim gebruik van de mechanica.

$switch automatische variabele

wanneer de switch zijn waarden verwerkt, maakt het een teller aan en noemt het $switch. Dit is een automatische variabele gemaakt door PowerShell en je kunt het direct manipuleren.

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

Dit geeft u de resultaten van:

24

door de enumerator naar voren te verplaatsen, wordt het volgende item niet verwerkt door de switch, maar u kunt deze waarde direct benaderen. Ik zou het waanzin noemen.

andere patronen

Hashtables

een van mijn meest populaire berichten is degene die ik deed op hashtables. Een van de use cases voor eenhashtable is een opzoektabel. Dat is een alternatieve benadering van een gemeenschappelijk patroon dat eenswitch statement vaak adresseert.

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

als ik alleen een switch als een lookup Gebruik, gebruik ik vaak een hashtable in plaats daarvan.

Enum

PowerShell 5.0 introduceerde de Enum en het is ook een optie in dit geval.

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

We kunnen de hele dag zoeken naar verschillende manieren om dit probleem op te lossen. Ik wilde er zeker van zijn dat je wist dat je opties had.

laatste woorden

Het switch statement is eenvoudig op het oppervlak, maar het biedt een aantal geavanceerde functies die de meeste mensen niet beseffen dat beschikbaar zijn. Rijgen die functies samen maakt dit een krachtige functie. Ik hoop dat je iets geleerd hebt dat je je nog niet had gerealiseerd.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *