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 $true
is.
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 Component
Role
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-CaseSensitive
gebruiken. 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 -File
parameter. 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.