- 05/23/2020
- 18 minuter att läsa
-
- j
- x
- t
- d
- s
liksom många andra språk har PowerShell uttalanden för villkorligt exekvering av kod i dinskript. En av dessa uttalanden är If-uttalandet., Idag kommer vi att ta ett djupt dyk in i en avDe mest grundläggande kommandona i PowerShell.
Obs
den ursprungliga versionen av denna artikel dök upp på bloggen skriven av @KevinMarquette. ThePowerShell team tack Kevin för att dela innehållet med oss. Vänligen kolla in hans blogg atPowerShellExplained.com.
villkorlig utförande
dina skript behöver ofta 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, dåutvärdera ett annat avsnitt av koden baserat på den utvärderingen. Detta är precis vadif
– satsen gör.
if-satsen
här är ett grundläggande exempel påif
– satsen:
$condition = $trueif ( $condition ){ Write-Output "The condition was true"}
det första somif
– satsen gör är att utvärdera uttrycket inom parentes. Om det utvärderar $true
, kör det scriptblock
I axlarna., Om värdet var $false
, skulle det hoppa över det scriptblock.
i föregående exempel utvärderadeif
– satsen bara variabeln$condition
. Det var$true
och skulle ha utfört kommandot Write-Output
inuti scriptblock.
på vissa språk kan du placera en enda rad med kod efter if
– uttalandet och det getsexecuted. Det är inte fallet i PowerShell. Du måste tillhandahålla en fullständigscriptblock
med hängslen forit att fungera korrekt.,
Jämförelseoperatörer
den vanligaste användningen avif
– satsen för är att jämföra två objekt med varandra. PowerShell harspeciella operatörer för olika jämförelsescenarier. När du använder en jämförelseoperatör, värdetpå vänster sida jämförs med värdet på höger sida.
-eq för jämlikhet
-eq
gör en jämlikhetskontroll mellan två värden för att se till att de är lika med varandra.,
$value = Get-MysteryValueif ( 5 -eq $value ){ # do something}
i det här exemplet tar jag ett känt värde för 5
och jämför det med min $value
för att se om theymatch.
ett möjligt användningsfall är att kontrollera statusen för ett värde innan du vidtar en åtgärd på det. Du kunde få en tjänst och kontrollera att statusen kördes innan du ringde Restart-Service
på 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 på theleft, det gör det misstaget mer besvärligt att göra.
den här operatören (och andra) har några variationer.,
-
-eq
case-okänslig jämlikhet -
-ieq
case-okänslig jämlikhet -
-ceq
fallkänslig jämlikhet
-ne inte lika
många operatörer har en relaterad operatör som kontrollerar motsatsen resultat. -ne
verifierar 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 är5
., En bra användning-fall därskulle vara att kontrollera om en tjänst var i körläge innan du försöker starta den.
variationer:
-
-ne
fall-okänslig inte lika -
-ine
fall-okänslig inte lika -
-cne
fallkänslig inte lika
dessa är inversa variationer av -cne
fallkänslig inte lika
id = ”626395ddfd” > . Jag grupperar dessa typer tillsammans när jag listar variationerfö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 -le
står för GreaterThan, GreaterThanOrEqual, kortare än, och LessThanOrEqual.,Eater än eller lika, case-okänslig
-cge
större än eller lika, case-sensitive-lt
mindre än-ilt
mindre än, case-okänslig-clt
mindre än, skiftlägeskänslig-le
mindre än eller lika-ile
mindre än eller lika, skiftlägeskänslig-cle
mindre än eller lika, skiftlägeskänsligJag vet inte varför du skulle använda skiftlägeskänslig 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.
-
?
matchar 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.,e”>
variationer:
-
-like
case-okänsliga jokertecken -
-ilike
case-okänsliga jokertecken -
-clike
case-känsliga jokertecken -
-notlike
Case-okänsliga jokertecken inte matchas -
-inotlike
case-okänsliga jokertecken inte matchas -
-cnotlike
skiftlägeskänsliga jokertecken inte matchas
-matcha Reguljärt uttryck
operatören -match
låter dig för att kontrollera en sträng för en Reguljärt uttrycksbaserad matchning., Använd dettanä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 regexmönster matchar var som helst i strängen som standard. Så du kan ange en substring somdu vill matcha 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 -match
ochDe många sätten att använda regex i en annan artikel.,
Variations:
-
-match
case-insensitive regex -
-imatch
case-insensitive regex -
-cmatch
case-sensitive regex -
-notmatch
case-insensitive regex not matched -
-inotmatch
case-insensitive regex not matched -
-cnotmatch
case-sensitive regex not matched
-is of type
You can check a value’s type with the -is
operator.,
if ( $value -is ){ # do something}
Du kan använda detta om du arbetar med klasser eller accepterar olika objekt över rörledningen. Du kan antingen ha en tjänst eller ett servicenamn som din inmatning. Kontrollera sedan om du har en tjänstoch hämta tjänsten om du bara har namnet.,
if ( $Service -isnot ){ $Service = Get-Service -Name $Service}
variationer:
-
-is
av typen -
-isnot
inte av typen
samlingsoperatörer
När du använder de tidigare operatörerna med ett enda värde är resultatet $true
eller $false
. Detta ishandled något annorlunda när man arbetar med en samling. Varje objekt i samlingen getsevalueras och operatören returnerar varje värde som utvärderar till $true
.,
PS> 1,2,3,4 -eq 33
detta fungerar fortfarande korrekt i ettif
– uttalande. Så ett värde returneras av din operatör, dåwhole-satsen är $true
.
$array = 1..6if ( $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. Använda-ne
med acollection returns$true
om något objekt i samlingen inte matchar ditt värde.,
PS> 1,2,3 -ne 4123
detta kan se ut som ett smart trick, men vi har operatörer -contains
och -in
som hanterar detta mereffektivt. Och-notcontains
gör vad du förväntar dig.
-innehåller
-contains
– operatören kontrollerar samlingen för ditt värde. Så snart den hittar en match, itreturns $true
.
$array = 1..6if ( $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ändaWhere-Object
(eller-eq
) går hela listan varje gång och är betydligt långsammare.,
variationer:
-
-contains
case-okänslig match -
-icontains
case-okänslig match -
-ccontains
case-känslig match -
-notcontains
case-okänslig inte matchad -
-inotcontains
Case-okänslig inte matchad -
-cnotcontains
skiftlägeskänslig inte matchad
-in
-in
operatören är precis som-contains
operatör utom samlingen är på höger sida.,
$array = 1..6if ( 3 -in $array ){ # do something}
Variations:
-
-in
case-insensitive match -
-iin
case-insensitive match -
-cin
case-sensitive match -
-notin
case-insensitive not matched -
-inotin
case-insensitive not matched -
-cnotin
case-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 variant där du inte behöver använda-not
– operatören. Men det finns fortfarande gånger det är användbart.
!, operator
Du kan använda !
som alias för -not
.
if ( -not $value ){}if ( !$value ){}
Du kan se!
används mer av personer som kommer från ett annat språk som C#. Jag föredrar att skriva itout eftersom jag har svårt att se när snabbt titta 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. Iadded extra parenteser för att göra det tydligare i det exemplet men de är valfria så länge expressionen ä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
, lämnar det tidigt och utför inte rätt jämförelse. Detta är praktiskt när du behöver se till att ett värde finns innandu använder det., Till exempel,Test-Path
kastar ett fel om du ger det en$null
sökväg.
if ( $null -ne $path -and (Test-Path -Path $path) )
-eller
-or
tillåter dig att 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 denförsta delen är $true
, är hela satsen $true
och den behandlar inte resten av expressionen.
notera också hur syntaxen fungerar för dessa operatörer. Du behöver två separata uttryck. Ihave sett användare försöker 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 är $true
är hela uttrycket $false
. Ett annat sätt atttitta 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 som Towy 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 resultatet., Undervisning bitwise operatörer är utanför ramen för denna artikel, men här är listan thedem.
-
-band
binär och -
-bor
binär eller -
-bxor
binär exklusiv eller -
-bnot
binär inte -
-shl
skift vänster -
-shr
Skift 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 återvänderandra värden.
if ( Get-Process Notepad* )
den utvärderar till$true
om det finns en returnerad process och$false
om det inte finns något., Det är korrekt att använda pipeline-uttryck eller andra PowerShell-uttryck som detta:
if ( Get-Process | Where Name -eq Notepad )
dessa uttryck kan kombineras med varandra med operatörerna -and
och -or
, men du kanmåste använda parentes för att bryta dem i subexpressioner.
if ( (Get-Process) -and (Get-Service) )
söker efter $null
har inget resultat eller ett$null
värde utvärderar till$false
Iif
– uttalandet., Vid kontrollspecifikt för $null
är det bästa sättet 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 att dyka djupare, har jag 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.,
if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}
normalt när du tilldelar ett värde till en variabel överförs inte värdet till rörledningen ellerkonsol. När du gör en variabel tilldelning i ett subuttryck, Det går vidare till thepipeline.
PS> $first = 1PS> ($second = 2)2
se hur tilldelningen$first
inte har någon utgång och tilldelningen$second
gör? När en överlåtelse görs i ett if
– uttalande, körs det precis som $second
– uppdraget ovan., Här är ett cleanexample om hur du kan använda det:
if ( $process = Get-Process Notepad* ){ $process | Stop-Process}
om$process
tilldelas ett värde, är uttalandet$true
och$process
stoppas.
se till att du inte förväxlar detta med-eq
eftersom detta inte är en jämlikhetskontroll. Detta är en moreobscure funktion som de flesta människor inte inser fungerar på detta sätt.,
alternativ körningssökväg
uttalandetif
låter dig ange en åtgärd för inte bara när uttalandet är$true
, men också 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 insidethem, 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 Vien annan kontroll och för att ge mer detaljerad information till användaren.
elseif
Vi är inte begränsade till bara en enda villkorlig kontroll., Vi kan kedjaif
ochelse
uttalandentillsammans istället för att häcka dem genom att användaelseif
uttalande.
utförandet sker från toppen till botten. Den övre if
– satsen utvärderas först. Om detta är $false
flyttas det ner till nästa elseif
eller else
I listan. Det sista else
är default-åtgärden att vidta om ingen av de andra returnerar$true
.,
byt
Vid denna tidpunkt måste jag nämnaswitch
– satsen. Det ger en alternativ syntax för att göraflera jämförelser med ett värde. Med switch
anger du ett uttryck och resultatet getscompared med flera olika värden. Om ett av dessa värden matchar är matchningskodblocket exekverat. 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 matchar det med Role
., Iused ett enkelt exempel bara för att ge dig viss exponering förswitch
– operatören. Jag pratar mer om allt du någonsin velat veta om switch-uttalandet i en annan artikel.
rörledning
rörledningen är ett unikt och viktigt inslag i PowerShell. Alla värden som inte suppressedor tilldelas en variabel placeras i rörledningen. if
ger oss ett sätt att ta fördel 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. Sedan tilldelar vi resultatet avif
– satsen till$discount
– variabeln. Det exemplet kunde ha lika lätttilldelat dessa värden till variabeln$discount
direkt i varje scriptblock. Jag kan inte säga att Iuse detta med if
uttalande ofta, men jag har ett exempel där jag använde detta nyligen.,
Array inline
Jag har en funktion som heter Invoke-SnowSql som lanserar en körbar med flera kommandoradsdokument. 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, kommer dessa värden att hamna 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 att kontrollera och dinIf
statement 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 som 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., Logicoperators-and
och-or
är bra operatörer att använda om du vill bryta ditt uttryck iflera linjer.
det är fortfarande mycket som händer där, men att placera varje bit på sin egen linje gör stor skillnad.Jag brukar använda detta när jag får mer än två jämförelser eller om jag måste rulla till höger förläs någon av logiken.
Pre-calculating results
Vi kan ta det uttalandet urif
– 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 avariable namn som förklarar vad det är att du verkligen kontrollerar. Detta är också och exempel påsjälvdokumenterande 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 använder vi aflag 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 enindividuell if
uttalande., Fördelen med detta är att när du felsöker kan du telexactly 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åsom 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 detta ser på aglance.,
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 enklare attarbeta med. Det gör denna kod lättare att testa. I dina tester kan du håna samtalet tillTest-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 är enklare eftersom det ärså liten.
kroppen av denna funktion kan fortfarande vara att en-liner vi började med eller den exploderade logik somvi använde i det sista avsnittet., Detta fungerar bra för båda scenarierna och låter dig enkelt ändra detgenomförandet senare.
felhantering
en viktig användning avif
– satsen är att kontrollera felförhållandena innan du kör in ifel. 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 egentligen inget undantag. Så kontrollera dina värden och validera dina villkor där du kan.,
om du vill dyka lite mer i faktisk undantagshantering, har jag en artikel omallt du någonsin velat veta om undantag.
sista ord
if
uttalande är en sådan enkel uttalande men är en 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.