liksom många andra språk har PowerShell uttalanden för att villkorligt exekvera kod i dina skript. En av dessa uttalanden är if-uttalandet. Idag kommer vi att ta en djupdykning i en av de mest grundläggande kommandona i PowerShell.,
- Index
- villkorligt utförande
- if-uttalandet
- Jämförelseoperatörer
- -eq för jämlikhet
- -ne inte lika
- – gt-ge-lt-le för större än eller mindre än
- -som jokertecken matcher
- -matcha reguljära uttryck
- -är av typen
- -är av typen
- -eq för jämlikhet
- samlingsoperatörer
- – innehåller
- – i
- logiska operatörer
- – inte
- !,pressions
- kontrollera för $null
- variabel tilldelning
- alternativ exekveringsväg
- else
- kapslade if
- elseif
- switch
- Pipeline
- Array inline
- förenkla komplexa operationer
- linje fortsättning
- Pre-calculating resultat
- multiple if uttalanden
- använda funktioner
- felhantering
- slutliga ord
villkorligt utförande
dina skript kommer ofta att behöva fatta beslut och utföra olika logik baserat på dessa beslut., Detta är vad jag menar med villkorligt utförande. Du har ett uttalande eller värde att utvärdera, sedan utföra en annan avsnitt av kod baserat på den utvärderingen. Detta är precis vad
if– satsen gör.if-satsen
här är ett mycket grundläggande exempel på
if– satsen:$condition = $true if ( $condition ) { Write-Output "The condition was true" }det första som
if– satsen gör är att utvärdera uttrycket inom parentes., Om den utvärderar till$true, kommer den att exekverascriptblockI hängslen. Om värdet var$false, skulle det hoppa över det scriptblock.i föregående exempel utvärderade
if– satsen bara variabeln$condition. Det var$trueoch skulle ha utfört kommandotWrite-Outputinuti scriptblock.på vissa språk kan du placera en enda rad kod efter
ifuttalande och det kommer att få exekveras., Så är inte fallet i PowerShell. Du måste tillhandahålla en fullständigscriptblockmed hängslen för att den ska fungera korrekt.Jämförelseoperatörer
det vanligaste Du kommer att använda
ifuttalande för är att jämföra två objekt med varandra. Powershell har speciella operatörer för olika jämförelsescenarier. När du använder en jämförelseoperatör jämförs värdet på vänster sida med värdet på höger sida.,-eq för jämlikhet
-eqgör en jämlikhetskontroll mellan två värden för att se till att de är lika med varandra.$value = Get-MysteryValue if ( 5 -eq $value ) { # do something }i det här exemplet tar jag ett känt värde på
5och jämför det med min$valueför att se om de matchar.en möjlig usecase är att kontrollera statusen för ett värde innan du vidtar en åtgärd på det. Du kan få en tjänst och kontrollera att statusen kördes innan du ringde
Restart-Servicepå den.,det är vanligt på andra språk som C# att använda
==för jämlikhet (ex:5 == $value) men det fungerar inte med powershell. Ett annat vanligt misstag som människor gör är att använda likhetstecknet (ex:5 = $value) som är reserverat för att tilldela värden till variabler. Genom att placera ditt kända värde till vänster gör det misstaget mer besvärligt att göra.den här operatören (och andra) har några variationer.,
-
-eqfall okänslig jämlikhet -
-ieqfall okänslig jämlikhet -
-ceqfall känslig jämlikhet
-ne inte lika
många operatörer har en relaterad operatör som kontrollerar det motsatta resultatet. – herr talman!
-neverifierar att värdena inte är lika med varandra.if ( 5 -ne $value ) { # do something }Använd detta för att se till att åtgärden endast utförs om värdet inte är
5., En bra användning-fall där skulle vara att kontrollera om en tjänst var i körläge innan du försöker starta den.variationer:
-
-nefall okänslig inte lika -
-inefall okänslig inte lika -
-cnefall känslig inte lika
dessa är bara inversa variationer av
-eq. Jag grupperar dessa typer tillsammans när jag listar variationer för andra operatörer.,-gt-ge-lt-L för större än eller mindre än
dessa operatörer används vid kontroll för att se om ett värde är större eller mindre än ett annat värde.
-gt -ge -lt -lestår för GreaterThan, GreaterThanOrEqual, kortare än, och LessThanOrEqual.,li>-cgestörre än eller lika, skiftlägeskänslig - !,pressions
-
-ltmindre än -
-iltmindre än, skiftlägeskänslig -
-cltmindre än, skiftlägeskänslig -
-lemindre än eller lika -
-ilemindre än eller lika, fall okänslig -
-clemindre än eller lika, skiftlägeskänslig
jag vet inte varför du skulle använda skiftlägeskänsliga och okänsliga alternativ för dessa operatörer.,
-liknande jokertecken
PowerShell har sin egen jokerbaserad mönstermatchningssyntax och du kan använda den med
-like– operatören. Dessa jokertecken mönster är ganska grundläggande.-
?kommer att matcha ett enda tecken -
*matchar valfritt antal tecken
$value = 'S-ATX-SQL01' if ( $value -like 'S-*-SQL??') { # do something }det är viktigt att påpeka att mönstret matchar hela strängen., Om du behöver matcha något mitt i strängen måste du placera
*I båda ändarna av strängen.,IV>variationer:
-
-likecase okänsliga jokertecken -
-ilikecase okänsliga jokertecken -
-clikecase känsliga jokertecken -
-notlikecase okänsliga jokertecken inte matchas -
-inotlikecase okänsliga jokertecken inte matchas -
-cnotlikecase känsliga jokertecken inte matchas
-matcha reguljära uttryck
-matchoperatören kan du kontrollera en sträng för ett reguljärt uttryck baserat match. – herr talman!, Använd detta när jokertecknen inte är tillräckligt flexibla för dig.$value = 'S-ATX-SQL01' if ( $value -match 'S-\w\w\w-SQL\d\d') { # do something }ett regex-mönster matchar som standard var som helst i strängen. Så du kan ange en substring som du vill ha matchad så här:
$value = 'S-ATX-SQL01' if ( $value -match 'SQL') { # do something }Regex är ett komplext språk av sig själv och värt att titta på. Jag pratar mer om
-matchoch de många sätten att använda regex i en annan artikel.,Variations:
-
-matchcase insensitive regex -
-imatchcase insensitive regex -
-cmatchcase sensitive regex -
-notmatchcase insensitive regex not matched -
-inotmatchcase insensitive regex not matched -
-cnotmatchcase sensitive regex not matched
-is of type
You are able to check a value’s type with the
-isoperator.,if ( $value -is ) { # do something }Du kan använda detta om du arbetar med klasser eller accepterar olika objekt över rörledningen. Du kan ha antingen en tjänst eller ett servicenamn som din ingång. Kontrollera sedan om du har en tjänst och hämta tjänsten om du bara har namnet.,
if ( $Service -isnot ) { $Service = Get-Service -Name $Service }variationer:
-
-isav typ -
-isnotinte av typ
Samlingsoperatörer
När du använder de tidigare operatörerna med ett enda värde är resultatet
$trueeller$false. Detta hanteras något annorlunda när man arbetar med en samling. Varje objekt i samlingen utvärderas och operatören returnerar istället varje värde som utvärderas till$true.,PS> 1,2,3,4 -eq 3 3detta fungerar fortfarande korrekt i ett
ifuttalande. Så ett värde returneras av din operatör, då är hela satsen$true.$array = 1..6 if ( $array -gt 3 ) { # do something }det finns en liten fälla som gömmer sig i detaljerna här som jag måste påpeka. När du använder
-ne– operatören på detta sätt är det lätt att felaktigt titta på logiken bakåt., Att använda-nemed en samling kommer att returnera$trueom något objekt i samlingen inte matchar ditt värde.PS> 1,2,3 -ne 4 1 2 3detta kan se ut som ett smart trick, men vi har operatörer
-containsoch-insom hanterar detta mer effektivt och-notcontainskommer att göra vad du förväntar dig.-innehåller
-contains– operatören kontrollerar samlingen för ditt värde., Så snart den hittar en matchning kommer den att returnera$true.$array = 1..6 if ( $array -contains 3 ) { # do something }det här är det bästa sättet att se om en samling innehåller ditt värde. Använda
Where-Object( eller-eq) kommer att gå hela listan varje gång och vara betydligt långsammare.,variationer:
-
-containsfall okänslig match -
-icontainsfall okänslig match -
-ccontainsfall känslig match -
-notcontainsfall okänslig match
-ccontainsfall känslig match - – inte
-
-notcontainsfall okänslig match inte matchas -
-inotcontainsfall okänslig inte matchas -
-cnotcontainsfall känslig inte matchas
-i
-in operatören är precis som -contains operatören utom samlingen är på höger sida.,
$array = 1..6 if ( 3 -in $array ) { # do something }
Variations:
-
-incase insensitive match -
-iincase insensitive match -
-cincase sensitive match -
-notincase insensitive not matched -
-inotincase insensitive not matched -
-cnotincase sensitive not matched
Logical operators
Logical operators are used to invert or combine other expressions.,
-inte
-not operatören vänder ett uttryck från$false till$true eller från$true till$false. Här är ett exempel där vi vill utföra en åtgärd när Test-Path är $false.
if ( -not ( Test-Path -Path $path ) )
de flesta av operatörerna vi pratade om har en variation där du inte skulle behöva använda-not – operatören, men det finns fortfarande gånger du skulle använda den.
!,
Du kan använda! som alias för-not.
if ( -not $value ){} if ( !$value ){}
du kommer att se ! används mer av personer som kommer från ett annat språk som C#. Jag föredrar att skriva ut det eftersom jag har svårt att se när jag snabbt tittar på mina skript.
-och
Du kan kombinera uttryck med-and – operatören. När du gör det måste båda sidorna vara $true för att hela uttrycket ska vara $true.,
if ( ($age -gt 13) -and ($age -lt 55) )
i det exemplet måste $age vara 13 eller äldre för vänster sida och mindre än 55 för höger sida. Jag lade till extra parenteser för att göra det tydligare i det exemplet men de är valfria så länge expresionen är enkel. Här är samma exempel utan dem.
if ( $age -gt 13 -and $age -lt 55 )
utvärdering sker från vänster till höger. Om det första objektet utvärderar till $false kommer det att avslutas tidigt och inte utföra rätt jämförelse., Detta är praktiskt när du behöver se till att ett värde finns innan du använder den. Test-Pathtill exempel kommer att kasta ett fel om du ger det en$null sökväg.
if ( $null -ne $path -and (Test-Path -Path $path) )
-eller
-or låter dig ange två uttryck och returnerar $true om någon av dem är $true.
if ( $age -le 13 -or $age -ge 55 )
precis som med-and – Operatören sker utvärderingen från vänster till höger., Förutom att om den första delen är $true är hela satsen $true och det kommer inte att behandla resten av uttrycket.
notera också hur syntaxen fungerar för dessa operatörer. Du behöver två separata uttryck. Jag har sett användare försöka göra något liknande $value -eq 5 -or 6 utan att inse deras misstag.
-xor exclusive eller
den här är lite ovanlig. -xor tillåter endast ett uttryck att utvärdera till$true., Så om båda objekten är $false eller båda objekten är $true, är hela uttrycket $false. Ett annat sätt att titta på detta är uttrycket är bara $true när resultaten av uttrycket är olika.
det är sällsynt att någon någonsin skulle använda denna logiska operatör och jag kan inte tänka mig ett bra exempel på varför jag någonsin skulle använda den.
Bitwise operators
Bitwise operators utför beräkningar på bitarna inom värdena och producerar ett nytt värde som resultat., Undervisning bitwise operatörer är utanför ramen för denna artikel, men här är listan dem.
-
-bandbinär och -
-borbinär eller -
-bxorbinär exklusiv eller -
-bnotbinär inte -
-shlskift vänster -
-shrSkift höger
PowerShell uttryck
Vi kan använda normal PowerShell inuti villkoret uttalande.,
if ( Test-Path -Path $Path )
Test-Path returnerar$true eller$false när den körs. Detta gäller även kommandon som returnerar andra värden.
if ( Get-Process Notepad* )
det kommer att utvärdera till $true om det finns en returnerad process och $false om det inte finns något., Det är helt giltigt att använda pipeline uttryck eller andra PowerShell uttalanden så här:
if ( Get-Process | Where Name -eq Notepad )
dessa uttryck kan kombineras med varandra med-and och-or operatörer, men du kan behöva använda parentes för att bryta dem i underuttryck.
if ( (Get-Process) -and (Get-Service) )
söker efter $null
har inget resultat eller ett$null värde utvärderar till$false Iif – uttalandet., När du kontrollerar specifikt för $nullär det en bästa praxis att placera $null på vänster sida.
if ( $null -eq $value )
det finns en hel del nyanser när man hanterar $null värden i PowerShell. Om du är intresserad av dykning djupare, jag har en artikel om allt du ville veta om $null.
variabel tilldelning
Jag glömde nästan att lägga till den här tills Prasoon Karunan V påminde mig om det.,
normalt när du tilldelar ett värde till en variabel överförs inte värdet till rörledningen eller konsolen. När du gör en variabel tilldelning i ett sub uttryck, det får vidare till rörledningen.
PS> $first = 1 PS> ($second = 2) 2
se hur tilldelningen$first inte har någon utgång och tilldelningen$second gör? När ett uppdrag görs i ett if – uttalande, kommer det att utföras precis som $second – uppdraget ovan., Här är ett rent exempel på hur du kan använda det:
if ( $process = Get-Process Notepad* ) { $process | Stop-Process }
om $process tilldelas ett värde, blir uttalandet $true och sedan stoppas $process.
se till att du inte förväxlar detta med-eq eftersom detta inte är en jämlikhetskontroll. Detta är en mer obskyr funktion som de flesta människor inte inser fungerar på detta sätt.,
alternativ exekveringsväg
uttalandetif låter dig ange en åtgärd för inte bara när uttalandet är$true, men också för när det är$false. Det är här else – satsen kommer till spel.
else
else – satsen är alltid den sista delen avif – satsen när den används.
i det här exemplet kontrollerar vi $path för att se till att det är en fil. Om vi hittar filen, flyttar vi den. Om inte, skriver vi en varning., Denna typ av förgreningslogik är mycket vanlig.
kapslade if
if ochelse uttalanden tar ett manusblock, så vi kan placera alla PowerShell-kommando inuti dem, inklusive en annanif – uttalande. Detta gör att du kan använda dig av mycket mer komplicerad logik.
i det här exemplet testar vi den lyckliga vägen först och vidtar sedan åtgärder på den. Om det misslyckas gör vi en annan kontroll och ger mer detaljerad information till användaren.
elseif
Vi är inte begränsade till bara en enda villkorlig kontroll., Vi kan kedja if och else – satser tillsammans istället för att häcka dem genom att använda elseif – satsen.
utförandet sker från toppen till botten. Den övre if – satsen utvärderas först. Om det är $false går det ner till nästa elseif eller else I listan. Det sista elseär standardåtgärden att vidta om ingen av de andra returnerar$true.,
byt
vid tis-punkten måste jag nämnaswitch – satsen. Det ger en alternativ syntax för att göra flera jämförelser med ett värde. Med switch anger du ett uttryck och det resultatet jämförs med flera olika värden. Om ett av dessa värden mach, körs matchande kodblocket. Ta en titt på det här exemplet:
$itemType = 'Role' switch ( $itemType ) { 'Component' { 'is a component' } 'Role' { 'is a role' } 'Location' { 'is a location' } }
det finns tre möjliga värden som kan matcha $itemType., I det här fallet kommer det att matcha med Role och is a role skulle bli exekverat. Jag använde ett mycket enkelt exempel bara för att ge dig lite exponering för switch – operatören. Jag pratar mer om allt du någonsin velat veta om switch uttalande i en annan artikel.
rörledning
rörledningen är ett mycket unikt och viktigt inslag i PowerShell. Alla värden som inte undertrycks eller tilldelas en variabel placeras i rörledningen., Den if ger oss ett sätt att dra nytta av rörledningen på ett sätt som inte alltid är uppenbart.
$discount = if ( $age -ge 55 ) { Get-SeniorDiscount } elseif ( $age -le 13 ) { Get-ChildDiscount } else { 0.00 }
varje scriptblock placerar resultaten kommandona eller värdet i rörledningen. Då tilldelar vi resultatet av if-satsen till variabeln$discount. Det exemplet kunde lika enkelt ha tilldelat dessa värden till variabeln$discount direkt i varje scriptblock., Jag kan inte säga att jag använder detta med if uttalande Mycket ofta, men jag har ett exempel där jag har använt detta nyligen.
Array inline
Jag har en funktion som heter Invoke-SnowSql som startar en körbar med flera kommandoradsargument. Här är ett klipp från den funktionen där jag bygger en rad argument.
variablerna$Debug och$Path är parametrar för funktionen som tillhandahålls av slutanvändaren. Jag utvärderar dem inline inuti initieringen av min array., Om$Debug är sant faller dessa värden i$snowSqlParam på rätt plats. Samma gäller för variabeln$Path.
förenkla komplexa operationer
det är oundvikligt att du stöter på en situation som har alldeles för många jämförelser för att kontrollera och ditt if-uttalande rullar långt från höger sida av skärmen.
de kan vara svåra att läsa och det gör dig mer benägen att göra misstag. Det finns några saker vi kan göra åt det.,
Line fortsättning
det finns några operatörer i PowerShell som låter dig slå in kommandot till nästa rad. De logiska operatörerna -andoch-or är bra operatörer att använda om du vill bryta ditt uttryck i flera rader.
det är fortfarande mycket som händer där, men att placera varje bit på sin egen linje gör stor skillnad. Jag brukar bara göra detta när jag får mer än två jämförelser eller om jag måste rulla till höger för att läsa någon av ligic.,
Pre-calculating results
Vi kan ta det uttalandet ur if-uttalandet och bara kontrollera resultatet.
det här känns bara mycket renare än det föregående exemplet. Du får också möjlighet att använda ett variabelnamn som förklarar vad det är att du verkligen kontrollerar. Detta är också och exempel på själv dokumentera kod som sparar onödiga kommentarer.
Multiple if-satser
Vi kan dela upp detta i flera satser och kontrollera dem en åt gången. I det här fallet kommer vi att använda en flagga eller en spårningsvariabel för att kombinera resultaten.,
jag var tvungen att invertera logiken för att få flagglogiken att fungera korrekt. Varje utvärdering är en individuellif uttalande. Fördelen med detta är att när du felsöker kan du berätta exakt vad logiken gör. Jag kunde lägga till mycket bättre verbositet samtidigt.
den uppenbara nackdelen är att det är så mycket mer kod att skriva. Koden är mer komplex att titta på eftersom det tar en enda rad logik och exploderar den i 25 eller flera linjer.
använda funktioner
Vi kan också flytta all valideringslogik till en funktion., Titta på hur rent det här ser ut i korthet.
if ( Test-SecureDriveConfiguration -ADUser $user ) { # do something }
Du måste fortfarande skapa funktionen för att göra valideringen, men det gör den här koden mycket lättare att arbeta med. Det gör denna kod lättare att testa. I dina tester kan du håna samtalet till Test-ADDriveConfiguration och du behöver bara två tester för den här funktionen. En där den returnerar $true och en där den returnerar $false. Att testa den andra funktionen blir enklare eftersom den är så liten.,
kroppen av den funktionen kan fortfarande vara att en-liner vi började med eller den exploderade logiken som vi använde i det sista avsnittet. Detta fungerar bra för båda scenarierna och låter dig enkelt ändra implementeringen senare.
felhantering
en väldigt viktig användning avif – satsen är att kontrollera felförhållandena innan du stöter på fel. Ett bra exempel är att kontrollera om en mapp redan finns innan du försöker skapa den.,
if ( -not (Test-Path -Path $folder) ) { New-Item -Type Directory -Path $folder }
Jag vill säga att om du förväntar dig att ett undantag ska hända, så är det inte riktigt ett undantag. Så kontrollera dina värden och validera dina villkor där du kan.
om du vill dyka lite mer i verklig undantagshantering har jag en artikel om allt du någonsin velat veta om undantag.
slutliga ord
if uttalande är en sådan enkel uttalande men är en mycket grundläggande del av PowerShell. Du kommer att hitta dig själv med hjälp av detta flera gånger i nästan varje skript du skriver., Jag hoppas att du har en bättre förståelse än du hade tidigare.