- 05/23/2020
- 18 minut do przeczytania
-
- j
- x
- t
- d
- s
podobnie jak wiele innych języków, PowerShell ma instrukcje warunkowo wykonywanie kodu w skryptach. Jednym z tych stwierdzeń jest stwierdzenie If., Dzisiaj przyjrzymy się jednej z najbardziej podstawowych komend w PowerShell.
Uwaga
Oryginalna wersja tego artykułu pojawiła się na blogu napisanym przez @KevinMarquette. Zespół ThePowerShell dziękuje Kevinowi za udostępnienie nam tych treści. Zapraszam na jego bloga atPowerShellExplained.com.
wykonanie warunkowe
Twoje Skrypty często muszą podejmować decyzje i wykonywać inną logikę opartą na tych decyzjach.To jest to, co mam na myśli przez warunkowe wykonanie., Masz jedną instrukcję lub wartość do oceny, a następnie wykonaj inną sekcję kodu na podstawie tej oceny. To jest dokładnie to, co robi if
.
Instrukcja if
oto podstawowy przykładif
Instrukcja:
$condition = $trueif ( $condition ){ Write-Output "The condition was true"}
pierwszą rzeczą, jaką robiif
jest Obliczanie wyrażenia w nawiasach. Jeżeli ocenia $true
, to wykonuje scriptblock
w nawiasie., Jeśli wartość była $false
, to przeskoczyłaby ten blok skryptów.
w poprzednim przykładzie polecenie if
oceniało zmienną $condition
. Było to$true
I wykonałoby polecenieWrite-Output
wewnątrz bloku skryptów.
w niektórych językach można umieścić pojedynczy wiersz kodu po instrukcji if
i zostanie on usunięty. W PowerShell tak nie jest. Musisz dostarczyć pełny scriptblock
z aparatem ortodontycznym, aby działał poprawnie.,
operatory porównywania
najczęstszym zastosowaniem instrukcjiif
jest porównanie dwóch elementów ze sobą. PowerShell ma specjalne operatory dla różnych scenariuszy porównawczych. W przypadku użycia operatora porównania wartość po lewej stronie jest porównywana z wartością po prawej stronie.
-eq dla równości
-eq
sprawdza równość dwóch wartości, aby upewnić się, że są one równe sobie.,
$value = Get-MysteryValueif ( 5 -eq $value ){ # do something}
w tym przykładzie biorę znaną wartość 5
I porównuję ją z moim $value
, aby sprawdzić, czy pasują.
jednym z możliwych przypadków użycia jest sprawdzenie stanu wartości przed podjęciem na niej działania. Można było uruchomić usługę i sprawdzić, czy status był uruchomiony przed wywołaniem Restart-Service
na nim.
w innych językach, takich jak C#, często używa się==
dla równości (np.5 == $value
), ale to nie działa z PowerShell., Innym częstym błędem, który ludzie popełniają jest użycie znaku równości (np:5 = $value
), który jest zarezerwowany do przypisywania wartości do zmiennych. Umieszczając swoją znaną wartość na liście, czyni ten błąd bardziej niezręcznym do popełnienia.
operator ten (i inne) ma kilka odmian.,
-
-eq
równość bez rozróżniania wielkości liter -
-ieq
równość bez rozróżniania wielkości liter -
-ceq
równość bez rozróżniania wielkości liter
-ne Nie równe
wiele operatorów ma operatora powiązanego, który sprawdza przeciwny wynik. -ne
sprawdza, czy wartości nie są sobie równe.
if ( 5 -ne $value ){ # do something}
Użyj tego, aby upewnić się, że akcja jest wykonywana tylko wtedy, gdy jej wartość nie jest5
., Dobre przypadki użycia, w których należy sprawdzić, czy usługa była w stanie działania, zanim spróbujesz ją uruchomić.
zmiany:
-
-ne
wielkość liter nie jest równa -
-ine
wielkość liter nie jest równa -
-cne
wielkość liter nie jest równa -
-cge
większa lub równa, rozróżniana wielkość liter -
-lt
mniej niż -
-ilt
mniej niż, rozróżniana wielkość liter -
-clt
mniej niż, rozróżniana wielkość liter -
-le
mniej niż lub równe -
-ile
mniej niż lub równe, rozróżniana wielkość liter -
-cle
mniejsza lub równa, rozróżniająca wielkość liter -
?
pasuje do dowolnego pojedynczego znaku -
*
pasuje do dowolnej liczby znaków -
-like
wieloznaczne rozróżnianie wielkości liter -
-ilike
wieloznaczne rozróżnianie wielkości liter -
-clike
wieloznaczne rozróżnianie wielkości liter -
-notlike
bez rozróżniania wielkości liter znaki wieloznaczne nie pasują -
-inotlike
bez rozróżniania wielkości liter znaki wieloznaczne nie pasują -
-cnotlike
bez rozróżniania wielkości liter znaki wieloznaczne nie pasują
ul
są to odwrotne odmiany-eq
. Będę grupować te typy razem, gdy wymienię wariacje dla innych operatorów.,
-gt-ge-lt-le dla większej lub mniejszej niż
operatory te są używane podczas sprawdzania, czy wartość jest większa lub mniejsza od innej wartości.-gt -ge -lt -le
oznacza GreaterThan, GreaterThanOrEqual, LessThan i LessThanOrEqual.,
Nie wiem, dlaczego używasz opcji rozróżniających wielkość liter i niewrażliwych dla tych operatorów.,
-podobne do wieloznacznych dopasowań
PowerShell ma własną składnię dopasowania wzorców opartą na wieloznacznych symbolach i można go używać z operatorem-like
. Te wzory wieloznaczne są dość podstawowe.
$value = 'S-ATX-SQL01'if ( $value -like 'S-*-SQL??'){ # do something}
ważne jest, aby zaznaczyć, że wzór pasuje do całego ciągu. Jeśli chcesz dopasować coś na środku łańcucha, musisz umieścić *
na obu końcach łańcucha.,e”>
wariacje:
-dopasuj Wyrażenie regularne
Operator -match
umożliwia sprawdzenie ciągu znaków pod kątem dopasowania opartego na wyrażeniach regularnych., Użyj tego, gdy wzory wieloznaczne nie są wystarczająco elastyczne dla Ciebie.
$value = 'S-ATX-SQL01'if ( $value -match 'S-\w\w\w-SQL\d\d'){ # do something}
wzorek regex domyślnie pasuje w dowolnym miejscu łańcucha. Możesz więc określić substring, który chcesz dopasować w następujący sposób:
$value = 'S-ATX-SQL01'if ( $value -match 'SQL'){ # do something}
Regex jest złożonym językiem, który sam w sobie jest wart przyjrzenia się. Mówię więcej o -match
I wiele sposobów użycia regex w innym artykule.,
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}
możesz tego użyć, jeśli pracujesz z klasami lub akceptujesz różne obiekty w potoku. Możesz mieć usługę lub nazwę usługi jako dane wejściowe. Następnie sprawdź, czy masz usługę i pobierz usługę, jeśli masz tylko nazwę.,
if ( $Service -isnot ){ $Service = Get-Service -Name $Service}
warianty:
-
-is
typu -
-isnot
Nie typu
operatory kolekcji
gdy używasz poprzedniego operatory z pojedynczą wartością, wynikiem jest $true
lub $false
. Nieco inaczej to wygląda podczas pracy z kolekcją. Każda pozycja w kolekcji jest ewaluowana, a operator zwraca każdą wartość, która jest ewaluowana do $true
.,
PS> 1,2,3,4 -eq 33
to nadal działa poprawnie w instrukcjiif
. Tak więc wartość jest zwracana przez operatora, wtedy Instrukcja whole jest $true
.
$array = 1..6if ( $array -gt 3 ){ # do something}
w szczegółach kryje się jedna mała pułapka, na którą muszę zwrócić uwagę. Używając operatora -ne
w ten sposób łatwo jest błędnie spojrzeć na logikę wstecz. Użycie -ne
zkolekcją zwraca$true
jeśli jakikolwiek element w kolekcji nie odpowiada twojej wartości.,
PS> 1,2,3 -ne 4123
może to wyglądać na sprytną sztuczkę, ale mamy operatory-contains
I-in
, które obsługują to bardziej efektywnie. I -notcontains
robi to, czego oczekujesz.
-zawiera
operator-contains
sprawdza kolekcję pod kątem Twojej wartości. Gdy tylko znajdzie dopasowanie, zwraca $true
.
$array = 1..6if ( $array -contains 3 ){ # do something}
jest to preferowany sposób sprawdzania, czy Kolekcja zawiera twoją wartość., Korzystanie z Where-Object
(lub-eq
) przechodzi przez całą listę za każdym razem i jest znacznie wolniejsze.,
zmiany:
-
-contains
dopasowanie rozróżniające wielkość liter -
-icontains
dopasowanie rozróżniające wielkość liter -
-ccontains
dopasowanie rozróżniające wielkość liter -
-inotcontains
wielkość liter nie jest dopasowana -
-cnotcontains
wielkość liter nie jest dopasowana
-notcontains
wielkość liter nie jest dopasowana
-w
jest taki sam jak operator-contains
z tym, że kolekcja znajduje się po prawej stronie.,
$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.,
-nie
-not
operator odwraca wyrażenie z $false
do $true
lub z $true
do $false
. Poniżej znajduje się przykład, w którym chcemy wykonać akcję, gdy Test-Path
jest $false
.
if ( -not ( Test-Path -Path $path ) )
większość operatorów, o których rozmawialiśmy, ma odmianę, w której nie trzeba używać operatora-not
. Ale są jeszcze czasy, że jest to przydatne.
!, operator
możesz użyć !
jako aliasu dla -not
.
if ( -not $value ){}if ( !$value ){}
Możesz zobaczyć!
używany bardziej przez ludzi, którzy pochodzą z innych języków, takich jak C#. Wolę to wpisać, ponieważ trudno mi to zobaczyć, gdy szybko przeglądam moje Skrypty.
-i
można łączyć wyrażenia za pomocą operatora-and
. Gdy to zrobisz, obie strony muszą być$true
, aby całe wyrażenie było $true
.,
if ( ($age -gt 13) -and ($age -lt 55) )
w tym przykładzie$age
musi mieć 13 lub więcej dla lewej strony i mniej niż 55 dla prawej strony. Dodałem dodatkowe nawiasy, aby było jaśniej w tym przykładzie, ale są opcjonalne, o ile ekspresja jest prosta. Oto ten sam przykład bez nich.
if ( $age -gt 13 -and $age -lt 55 )
ocena odbywa się od lewej do prawej. Jeśli pierwsza pozycja zostanie oceniona na $false
, zakończy się wcześniej i nie wykona właściwego porównania. Jest to przydatne, gdy musisz upewnić się, że wartość istnieje przed jej użyciem., Na przykład Test-Path
wyświetla błąd, jeśli nadasz mu ścieżkę $null
.
if ( $null -ne $path -and (Test-Path -Path $path) )
-lub
-or
pozwala określić dwa wyrażenia i zwraca$true
jeśli jedno z nich to$true
.
if ( $age -le 13 -or $age -ge 55 )
podobnie jak w przypadku operatora-and
, ocena odbywa się od lewej do prawej., Z tym wyjątkiem, że jeśli pierwsza część jest $true
, to cała instrukcja jest $true
I nie przetwarza reszty wyrażenia.
zanotuj również, jak działa składnia tych operatorów. Potrzebujesz dwóch oddzielnych wyrażeń. Widziałem, jak użytkownicy próbują zrobić coś takiego $value -eq 5 -or 6
nie zdając sobie sprawy z błędu.
-XOR exclusive lub
ten jest trochę nietypowy. -xor
pozwala na ewaluację tylko jednego wyrażenia do$true
., Więc jeśli oba elementy są $false
lub oba elementy są $true
, to całe wyrażenie jest $false
. Innym sposobem na to jest wyrażenie tylko $true
, gdy wyniki wyrażenia są różne.
rzadko kiedy ktoś używa tego operatora logicznego i nie mogę wymyślić dobrego przykładu, jak bym go kiedykolwiek użył.
operatory bitowe
operatory bitowe wykonują obliczenia na bitach w wartościach i wytwarzają nową wartość jako wynik., Nauczanie operatorów bitowych wykracza poza zakres tego artykułu, ale tutaj znajduje się ich lista.
-
-band
binary I -
-bor
binary lub -
-bxor
Binary exclusive lub -
-bnot
Binary not -
-shl
shift left -
-shr
shift right
wyrażenia PowerShell
możemy użyć zwykłego PowerShell ' a wewnątrz instrukcji condition.,
if ( Test-Path -Path $Path )
Test-Path
zwraca$true
lub$false
podczas wykonywania. Dotyczy to również poleceń zwracających inne wartości.
if ( Get-Process Notepad* )
ewaluuje do$true
jeśli istnieje zwrócony proces i$false
jeśli nic nie ma., Używanie wyrażeń potoków lub innych wyrażeń PowerShell jak to:
if ( Get-Process | Where Name -eq Notepad )
wyrażenia te można łączyć ze sobą za pomocą operatorów -and
I -or
, ale możesz użyć nawiasu, aby podzielić je na podwyrażenia.
if ( (Get-Process) -and (Get-Service) )
sprawdzanie $null
Bez wyniku lub$null
wartość oblicza się na$false
w instrukcjiif
., Podczas sprawdzania $null
najlepiej jest umieścić $null
po lewej stronie.
if ( $null -eq $value )
wartości$null
w PowerShell są bardzo niuanse. Jeśli jesteś zainteresowany nurkowaniem głębiej, mam artykuł o wszystkim, co chciałeś wiedzieć o $null.
przypisanie zmiennej
prawie zapomniałem dodać tę, dopóki nie przypomniał mi o tym Prasoon Karunan V.,
if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}
zwykle gdy przypisujesz wartość do zmiennej, wartość ta nie jest przekazywana do potoku orconsole. Gdy wykonujesz przypisanie zmiennej w wyrażeniu podrzędnym, jest ono przekazywane do thepipeline.
PS> $first = 1PS> ($second = 2)2
zobacz, jak przypisanie$first
nie ma wyjścia, a przypisanie$second
robi? Gdy przypisanie jest wykonywane w instrukcji if
, wykonuje się tak samo jak przypisanie $second
powyżej., Poniżej znajduje się przykład jak możesz go użyć:
if ( $process = Get-Process Notepad* ){ $process | Stop-Process}
Jeśli $process
otrzymuje przypisaną wartość, to polecenie jest $true
I $process
zostaje zatrzymane.
upewnij się, że nie pomylisz tego z-eq
, ponieważ nie jest to sprawdzanie równości. Jest to bardziej funkcja, której większość ludzi nie zdaje sobie sprawy, że działa w ten sposób.,
alternatywna ścieżka wykonania
polecenieif
pozwala określić akcję nie tylko wtedy, gdy jest to$true
, ale także wtedy, gdy jest to$false
. W tym miejscu wchodzi w grę else
.
else
Instrukcjaelse
jest zawsze ostatnią częścią instrukcjiif
gdy jest używana.
w tym przykładzie sprawdzamy $path
, aby upewnić się, że jest to plik. Jeśli znajdziemy plik, przeniesiemy go. Jeśli nie, napiszemy Ostrzeżenie., Ten rodzaj logiki rozgałęzień jest bardzo powszechny.
zagnieżdżone if
if
orazelse
pobierają blok skryptu, dzięki czemu możemy umieścić w nim dowolne polecenie PowerShell, w tym inne polecenieif
. Pozwala to na wykorzystanie znacznie bardziej skomplikowanej logiki.
w tym przykładzie najpierw testujemy szczęśliwą ścieżkę, a następnie podejmujemy na niej działania. Jeśli to się nie powiedzie, wykonujemy kolejną kontrolę i przekazujemy użytkownikowi bardziej szczegółowe informacje.
elseif
nie ograniczamy się tylko do jednego warunkowego sprawdzenia., Możemy połączyć if
I else
statementstogether zamiast zagnieżdżać je za pomocą elseif
statement.
wykonanie odbywa się od góry do dołu. Topif
jest obliczana jako pierwsza. Jeśli to $false
, to przechodzi w dół do następnego elseif
lub else
na liście. Ta ostatnia else
jest ostatnią akcją, którą należy wykonać, jeśli żadna z pozostałych nie zwróci $true
.,
switch
w tym momencie Muszę wspomnieć oswitch
. Zapewnia alternatywną składnię do roingmultiple porównań z wartością. Za pomocą switch
można określić wyrażenie, a wynik zostanie porównany z kilkoma różnymi wartościami. Jeśli jedna z tych wartości pasuje, pasujący blok kodu jest usuwany. Spójrz na ten przykład:
$itemType = 'Role'switch ( $itemType ){ 'Component' { 'is a component' } 'Role' { 'is a role' } 'Location' { 'is a location' }}
istnieją trzy możliwe wartości, które mogą pasować do $itemType
. W tym przypadku pasuje do Role
., Użyłem prostego przykładu, aby dać ci trochę ekspozycji na operatorswitch
. O wszystkim, co chcielibyście wiedzieć o wypowiedziach switch, opowiadam w innym artykule.
Pipeline
pipeline jest unikalną i ważną cechą PowerShell. Każda wartość, która nie jest przypisana do zmiennej zostanie umieszczona w potoku. if
zapewnia nam sposób wykorzystania potoku w sposób, który nie zawsze jest oczywisty.,
$discount = if ( $age -ge 55 ){ Get-SeniorDiscount}elseif ( $age -le 13 ){ Get-ChildDiscount}else{ 0.00}
każdy blok skryptu umieszcza wyniki poleceń lub wartość w potoku. Następnie przypisujemy wynik instrukcji if
do zmiennej $discount
. Ten przykład mógł równie łatwo przypisać te wartości do zmiennej $discount
bezpośrednio w każdym bloku skryptów. Nie mogę powiedzieć, że używam tego często z if
, ale mam przykład, w którym ostatnio tego używałem.,
tablica inline
mam funkcję o nazwie Invoke-SnowSql, która uruchamia plik wykonywalny z kilkoma dokumentami z linii poleceń. Oto klip z tej funkcji, gdzie buduję tablicę argumentów.
zmienne$Debug
I$Path
są parametrami funkcji, które są dostarczane przez użytkownika końcowego.Oceniam je inline wewnątrz inicjalizacji mojej tablicy. Jeśli $Debug
jest prawdziwe, to wartości te trafiają do $snowSqlParam
we właściwym miejscu. To samo dotyczy zmiennej $Path
.,
Uprość złożone operacje
jest nieuniknione, że napotkasz sytuację, która ma zbyt wiele porównań do sprawdzenia, a twojeIf
polecenie przewija się z prawej strony ekranu.
mogą być trudne do odczytania, a to sprawia, że jesteś bardziej podatny na popełnianie błędów. Jest kilka rzeczy, które możemy z tym zrobić.
kontynuacja linii
w PowerShell są operatory, które pozwalają zawinąć polecenie do następnej linii., Logicaloperatory -and
I -or
są dobrymi operatorami, których można użyć, jeśli chcesz podzielić wyrażenie na wiele wierszy.
jeszcze dużo się tam dzieje, ale umieszczenie każdego kawałka na własnej linii robi dużą różnicę.Generalnie używam tego, gdy dostaję więcej niż dwa porównania lub jeśli muszę przewijać w prawo, aby odczytać którąkolwiek logikę.
wstępne obliczanie wyników
możemy wyjąć to polecenie zif
I sprawdzić tylko wynik.
to po prostu wydaje się dużo czystsze niż w poprzednim przykładzie., Masz również możliwość użycia różnej nazwy, która wyjaśnia, co naprawdę sprawdzasz. Jest to również i przykład samodzielnego dokumentowania kodu, który zapisuje niepotrzebne komentarze.
wiele poleceń if
możemy podzielić je na wiele poleceń i sprawdzać je pojedynczo. W tym przypadku używamy aflag lub zmiennej śledzącej do łączenia wyników.
musiałem odwrócić logikę, aby logika flagi działała poprawnie. Każda ocena jest osobnym if
oświadczeniem., Zaletą tego jest to, że podczas debugowania można tellexactly co robi logika. Udało mi się dodać znacznie lepszą słowność w tym samym czasie.
oczywistym minusem jest to, że jest to o wiele więcej kodu do napisania. Kod jest bardziej złożony, aby spojrzeć na niego, ponieważ zajmuje pojedynczą linię logiki i eksploduje ją na 25 lub więcej linii.
używając funkcji
możemy również przenieść całą logikę walidacji do funkcji. Zobacz, jak czysto to wygląda w aglance.,
if ( Test-SecureDriveConfiguration -ADUser $user ){ # do something}
musisz jeszcze utworzyć funkcję, aby zrobić walidację, ale to znacznie ułatwia pracę z tym kodem. Ułatwia to testowanie tego kodu. W swoich testach możesz wywołać wywołanieTest-ADDriveConfiguration
I potrzebujesz tylko dwóch testów dla tej funkcji. Jeden, w którym zwraca$true
I drugi, w którym zwraca $false
. Testowanie drugiej funkcji jest prostsze, ponieważ jest mała.
ciało tej funkcji może nadal być tym jednowierszowym, od którego zaczęliśmy lub logiką, której użyliśmy w ostatniej sekcji., To działa dobrze dla obu scenariuszy i pozwala łatwo zmienić, żemplementation później.
obsługa błędów
jednym z ważnych zastosowań instrukcjiif
jest sprawdzenie warunków błędów przed uruchomieniem intoerrors. Dobrym przykładem jest sprawdzenie, czy folder już istnieje, zanim spróbujesz go utworzyć.
if ( -not (Test-Path -Path $folder) ){ New-Item -Type Directory -Path $folder}
Lubię powiedzieć, że jeśli spodziewasz się wystąpienia wyjątku, to tak naprawdę nie jest to wyjątek. Więc sprawdź swoje wartości i zweryfikuj swoje warunki, gdzie możesz.,
Jeśli chcesz zagłębić się nieco bardziej w rzeczywistą obsługę wyjątków, mam artykuł o wszystkim, co kiedykolwiek chciałeś wiedzieć o wyjątkach.
Ostatnie słowa
if
oświadczenie jest takie proste, ale jest podstawowym elementem PowerShell. Przekonasz się, że używasz tego wiele razy w prawie każdym skrypcie, który piszesz. Mam nadzieję, że masz lepsze zrozumienie niż wcześniej.