- 05/23/2020
- 18 minuti per leggere
-
- j
- x
- t
- D
Come molti altri linguaggi, PowerShell ha istruzioni per condizionalmente l’esecuzione di codice in yourscripts. Una di queste affermazioni è la dichiarazione If., Oggi faremo un tuffo profondo in uno deii comandi più fondamentali in PowerShell.
Nota
La versione originale di questo articolo è apparso sul blog scritto da @KevinMarquette. Il team di PowerShell ringrazia Kevin per aver condiviso questo contenuto con noi. Si prega di controllare il suo blog atPowerShellExplained.com.
Esecuzione condizionale
I tuoi script spesso devono prendere decisioni ed eseguire logiche diverse in base a tali decisioni.Questo è ciò che intendo per esecuzione condizionale., Hai un’istruzione o un valore da valutare, quindi esegui un’altra sezione di codice in base a tale valutazione. Questo è esattamente ciò che fa l’istruzione if
.
L’istruzione if
Ecco un esempio di base dell’istruzione if
:
$condition = $trueif ( $condition ){ Write-Output "The condition was true"}
La prima cosa che l’istruzione if
fa è valutare l’espressione tra parentesi. Se si evaluatesto $true
, quindi esegue il scriptblock
tra parentesi graffe., Se il valore era $false
, allora salterebbe su quel scriptblock.
Nell’esempio precedente, l’istruzioneif
stava solo valutando la variabile$condition
. Era $true
e avrebbe eseguito il comando Write-Output
all’interno dello scriptblock.
In alcune lingue, è possibile inserire una singola riga di codice dopo l’istruzione if
e viene eseguita. Questo non è il caso di PowerShell. È necessario fornire un scriptblock
completo con le parentesi graffe affinché funzioni correttamente.,
Operatori di confronto
L’uso più comune dell’istruzioneif
per sta confrontando due elementi tra loro. PowerShell haoperatori speciali per diversi scenari di confronto. Quando si utilizza un operatore di confronto, il valoresul lato sinistro viene confrontato con il valore sul lato destro.
-eq per l’uguaglianza
Il -eq
esegue un controllo di uguaglianza tra due valori per assicurarsi che siano uguali tra loro.,
$value = Get-MysteryValueif ( 5 -eq $value ){ # do something}
In questo esempio, sto prendendo un valore noto di5
e confrontandolo con il mio$value
per vedere se theymatch.
Un possibile caso d’uso è quello di controllare lo stato di un valore prima di intraprendere un’azione su di esso. È possibile ottenere un servizio e verificare che lo stato fosse in esecuzione prima di chiamare Restart-Service
su di esso.
È comune in altri linguaggi come c# usare ==
per l’uguaglianza (es: 5 == $value
) ma questo non funziona con PowerShell., Un altro errore comune che le persone fanno è usare il segno di uguale (es:5 = $value
) che è riservato per l’assegnazione di valori alle variabili. Mettendo il tuo valore conosciuto sulleft, rende quell’errore più imbarazzante da fare.
Questo operatore (e altri) ha alcune varianti.,
-
-eq
case-insensitive uguaglianza -
-ieq
case-insensitive uguaglianza -
-ceq
case-sensitive uguaglianza
-ne non è uguale
Molti operatori hanno un correlato operatore di controllo per il risultato opposto. -ne
verifica che i valori non siano uguali tra loro.
if ( 5 -ne $value ){ # do something}
Utilizzare questa opzione per assicurarsi che l’azione venga eseguita solo se il valore non è 5
., Un buon caso d’uso in cui sarebbe quello di verificare se un servizio era in esecuzione prima di provare ad avviarlo.
le Variazioni:
-
-ne
case-insensitive non uguale -
-ine
case-insensitive non uguale -
-cne
maiuscole e minuscole non è uguale
Queste sono le inverse variazioni di -eq
. Raggrupperò questi tipi insieme quando elencherò variationsfor altri operatori.,
-gt-ge-lt-le per maggiore o minore di
Questi operatori vengono utilizzati quando si controlla se un valore è maggiore o minore di un altro valore.Il-gt -ge -lt -le
sta per GreaterThan, GreaterThanOrEqual, LessThan e LessThanOrEqual.,mangiatore di o uguale, senza maiuscole / minuscole
-cge
maggiore o uguale distinzione tra maiuscole e minuscole-lt
meno-ilt
meno, case-insensitive-clt
meno di distinzione tra maiuscole e minuscole-le
minore o uguale-ile
minore o uguale a case-insensitive-cle
minore o uguale a case-sensitivenon so perché utilizzare maiuscole e minuscole e insensibile opzioni per questi operatori.,
-come jolly corrisponde
PowerShell ha una propria sintassi pattern matching basato su jolly e si può usare con il-like
operatore. Questi modelli di caratteri jolly sono abbastanza semplici.
-
?
corrisponde a qualsiasi carattere singolo -
*
corrisponde a qualsiasi numero di caratteri
$value = 'S-ATX-SQL01'if ( $value -like 'S-*-SQL??'){ # do something}
e ‘ importante sottolineare che il modello corrisponde a tutta la stringa. Se è necessario abbinare qualcosa nel mezzo della stringa, è necessario posizionare il *
su entrambe le estremità della stringa.,e”>
le Variazioni:
-
-like
case-insensitive jolly -
-ilike
case-insensitive jolly -
-clike
case-sensitive jolly -
-notlike
case-insensitive jolly non abbinato -
-inotlike
case-insensitive jolly non abbinato -
-cnotlike
case-sensitive jolly non abbinato
-match espressione regolare
-match
operatore permette di controllare una stringa per una delle espressioni regolari-based match., Usa questoquando i modelli jolly non sono abbastanza flessibili per te.
$value = 'S-ATX-SQL01'if ( $value -match 'S-\w\w\w-SQL\d\d'){ # do something}
Un modello regex corrisponde in qualsiasi punto della stringa per impostazione predefinita. Quindi puoi specificare una sottostringa che vuoi abbinare in questo modo:
$value = 'S-ATX-SQL01'if ( $value -match 'SQL'){ # do something}
Regex è un linguaggio complesso a sé stante e vale la pena esaminare. Parlo di più su -match
ei molti modi per usare regex in un altro articolo.,
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}
Puoi usarlo se stai lavorando con classi o accettando vari oggetti sulla pipeline. Youcould avere un servizio o un nome di servizio come input. Quindi controlla se hai un servizie recupera il servizio se hai solo il nome.,
if ( $Service -isnot ){ $Service = Get-Service -Name $Service}
le Variazioni:
-
-is
tipo -
-isnot
non è del tipo
Collezione operatori
Quando si utilizzano gli operatori precedenti con un solo valore, il risultato è $true
o $false
. Questo è gestito in modo leggermente diverso quando si lavora con una collezione. Ogni elemento della raccolta viene valutato e l’operatore restituisce ogni valore che viene valutato in $true
.,
PS> 1,2,3,4 -eq 33
Funziona ancora correttamente in un’istruzione if
. Quindi un valore viene restituito dal tuo operatore, quindi l’intera istruzione è $true
.
$array = 1..6if ( $array -gt 3 ){ # do something}
C’è una piccola trappola che si nasconde nei dettagli qui che devo sottolineare. Quando si utilizza l’operatore-ne
in questo modo, è facile guardare erroneamente la logica all’indietro. L’utilizzo di-ne
con acollection restituisce$true
se qualsiasi elemento della raccolta non corrisponde al valore.,
PS> 1,2,3 -ne 4123
Questo può sembrare un trucco intelligente, ma abbiamo operatori-contains
e-in
che gestiscono questo piùefficientemente. E-notcontains
fa quello che ti aspetti.
-contiene
L’operatore-contains
controlla la raccolta per il tuo valore. Non appena trova una corrispondenza, itreturns $true
.
$array = 1..6if ( $array -contains 3 ){ # do something}
Questo è il modo preferito per vedere se una raccolta contiene il tuo valore., UtilizzandoWhere-Object
(o-eq
) l’intero elenco viene visualizzato ogni volta ed è significativamente più lento.,
le Variazioni:
-
-contains
case-insensitive match -
-icontains
case-insensitive match -
-ccontains
distinzione tra maiuscole e minuscole -
-notcontains
case-insensitive non abbinato -
-inotcontains
case-insensitive non abbinato -
-cnotcontains
maiuscole e minuscole non abbinato
in
-in
operatore è come il -contains
operatore tranne la collezione è sulla destra-lato.,
$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.,
non
-not
operatore ribalta un’espressione $false
$true
o del $true
$false
. Ecco un esempio in cui vogliamo eseguire un’azione quando Test-Path
è $false
.
if ( -not ( Test-Path -Path $path ) )
La maggior parte degli operatori di cui abbiamo parlato ha una variazione in cui non è necessario utilizzare l’operatore-not
. Ma ci sono ancora volte che è utile.
!, operatore
È possibile utilizzare!
come alias per-not
.
if ( -not $value ){}if ( !$value ){}
Potresti vedere!
usato più da persone che provengono da altre lingue come c#. Preferisco digitare itout perché trovo difficile vedere quando guardo rapidamente i miei script.
-e
È possibile combinare espressioni con l’operatore-and
. Quando lo fai, entrambi i lati devono essere $true
perché l’intera espressione sia$true
.,
if ( ($age -gt 13) -and ($age -lt 55) )
In questo esempio,$age
deve essere uguale o superiore a 13 per il lato sinistro e inferiore a 55 per il lato destro. Ho aggiunto parentesi extra per renderlo più chiaro in quell’esempio, ma sono opzionali purché theexpression sia semplice. Ecco lo stesso esempio senza di loro.
if ( $age -gt 13 -and $age -lt 55 )
La valutazione avviene da sinistra a destra. Se il primo elemento viene valutato in $false
, esce presto e non esegue il confronto corretto. Questo è utile quando è necessario assicurarsi che un valore esiste beforeyou usarlo., Ad esempio, Test-Path
genera un errore se gli si assegna un percorso $null
.
if ( $null -ne $path -and (Test-Path -Path $path) )
-o
-or
consente di specificare due espressioni e restituisce $true
se uno di loro è$true
.
if ( $age -le 13 -or $age -ge 55 )
Proprio come con l’operatore -and
, la valutazione avviene da sinistra a destra., Tranne che se la prima parte è $true
, allora l’intera istruzione è $true
e non elabora il resto dell’espressione.
Nota anche come funziona la sintassi per questi operatori. Hai bisogno di due espressioni separate. Ho visto gli utenti provare a fare qualcosa di simile $value -eq 5 -or 6
senza rendersi conto del loro errore.
-xor exclusive o
Questo è un po ‘ insolito. -xor
consente a una sola espressione di valutare$true
., Quindi se entrambi gli elementi sono$false
o entrambi gli elementi sono$true
, allora l’intera espressione è$false
. Un altro modo per guardare a questo è che l’espressione è solo $true
quando i risultati dell’espressione sono diversi.
È raro che qualcuno possa mai usare questo operatore logico e non riesco a trovare un buon esempio come se lo usassi mai.
Operatori bit a bit
Gli operatori bit a bit eseguono calcoli sui bit all’interno dei valori e producono un nuovo valore come risultato., Insegnare agli operatori bitwise è oltre lo scopo di questo articolo, ma ecco la lista thethem.
-
-band
binario E -
-bor
binario O -
-bxor
binario esclusiva O -
-bnot
binario NON -
-shl
shift a sinistra -
-shr
shift a destra
PowerShell espressioni
Si può usare il normale PowerShell all’interno della condizione.,
if ( Test-Path -Path $Path )
Test-Path
restituisce$true
o$false
quando viene eseguito. Questo vale anche per i comandi che restituisconoaltri valori.
if ( Get-Process Notepad* )
Valuta$true
se c’è un processo restituito e$false
se non c’è niente., È perfettamente valido utilizzare espressioni pipeline o altre istruzioni PowerShell come questa:
if ( Get-Process | Where Name -eq Notepad )
Queste espressioni possono essere combinate tra loro con gli operatori-and
e-or
, ma è possibile utilizzare le parentesi per suddividerle in sottoespressioni.
if ( (Get-Process) -and (Get-Service) )
Controllo per $null
Avere un risultato o di un $null
valore restituisce $false
nel if
istruzione., Quando si controlla specificatamente per $null
, è consigliabile posizionare $null
sul lato sinistro.
if ( $null -eq $value )
Ci sono alcune sfumature quando si tratta di $null
valori in PowerShell. Se sei interessato a fare immersioni più profonde, ho un articolo su tutto ciò che volevi sapere su null null.
Assegnazione variabile
Ho quasi dimenticato di aggiungere questo fino a quando Prasoon Karunan V me lo ha ricordato.,
if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}
Normalmente quando si assegna un valore a una variabile, il valore non viene passato alla pipeline o alla console. Quando si esegue un’assegnazione variabile in un’espressione secondaria, viene passata a thepipeline.
PS> $first = 1PS> ($second = 2)2
Vedi come l’assegnazione $first
non ha output e l’assegnazione $second
? Quando un’assegnazione viene eseguita in un’istruzioneif
, viene eseguita proprio come l’assegnazione$second
sopra., Ecco un esempio pulito su come è possibile utilizzarlo:
if ( $process = Get-Process Notepad* ){ $process | Stop-Process}
Se $process
viene assegnato un valore, l’istruzione è $true
e $process
viene interrotta.
Assicurati di non confonderlo con-eq
perché questo non è un controllo di uguaglianza. Questa è una funzione moreobscure che la maggior parte delle persone non si rende conto funziona in questo modo.,
Percorso di esecuzione alternativo
L’istruzioneif
consente di specificare un’azione non solo quando l’istruzione è$true
, maanche quando è$false
. È qui che entra in gioco l’istruzioneelse
.
else
L’istruzioneelse
è sempre l’ultima parte dell’istruzioneif
quando viene utilizzata.
In questo esempio, controlliamo $path
per assicurarci che sia un file. Se troviamo il file, lo spostiamo. Ifnot, scriviamo un avvertimento., Questo tipo di logica di ramificazione è molto comune.
Annidato se
Le istruzioniif
eelse
prendono un blocco di script, quindi possiamo inserire qualsiasi comando PowerShell all’interno di esse, inclusa un’altra istruzioneif
. Ciò consente di utilizzare una logica molto più complicata.
In questo esempio, testiamo prima il percorso felice e poi agiamo su di esso. Se ciò non riesce, facciamo un altro controllo e per fornire informazioni più dettagliate all’utente.
elseif
Non siamo limitati a un solo controllo condizionale., Possiamo concatenareif
eelse
statementstogether invece di nidificarli usando l’istruzioneelseif
.
L’esecuzione avviene dall’alto verso il basso. L’istruzione topif
viene valutata per prima. Se questo è$false
, quindi passa al successivoelseif
oelse
nell’elenco. Quest’ultimaelse
è l’azione predefinita da intraprendere se nessuna delle altre restituisce$true
.,
switch
A questo punto, ho bisogno di menzionare l’istruzione switch
. Fornisce una sintassi alternativa per fare confronti multipli con un valore. Conswitch
, si specifica un’espressione e il risultato viene confrontato con diversi valori diversi. Se uno di questi valori corrisponde, il blocco di codice corrispondente isexecuted. Dai un’occhiata a questo esempio:
$itemType = 'Role'switch ( $itemType ){ 'Component' { 'is a component' } 'Role' { 'is a role' } 'Location' { 'is a location' }}
Ci sono tre possibili valori che possono corrispondere a $itemType
. In questo caso, corrisponde a Role
., Ho usato un semplice esempio solo per darti un po ‘ di esposizione all’operatore switch
. Parlo moreabout tutto quello che avreste sempre voluto sapere sulla dichiarazione switch in un altro articolo.
Pipeline
La pipeline è una caratteristica unica e importante di PowerShell. Qualsiasi valore che non è suppressedor assegnato a una variabile viene inserito nella pipeline. if
ci fornisce un modo per sfruttare la pipeline in un modo che non è sempre ovvio.,
$discount = if ( $age -ge 55 ){ Get-SeniorDiscount}elseif ( $age -le 13 ){ Get-ChildDiscount}else{ 0.00}
Ogni blocco di script inserisce i risultati i comandi o il valore nella pipeline. Quindi assegniamo il risultato dell’istruzioneif
alla variabile$discount
. Quell’esempio avrebbe potuto altrettanto facilmente assegnare quei valori alla variabile$discount
direttamente in ogni scriptblock. Non posso dire che lo usi spesso con l’istruzione if
, ma ho un esempio in cui l’ho usato di recente.,
Array inline
Ho una funzione chiamata Invoke-SnowSql che avvia un eseguibile con diversi comandi-linearguments. Ecco una clip da quella funzione in cui costruisco la serie di argomenti.
Le variabili$Debug
e$Path
sono parametri sulla funzione forniti dall’utente finale.Li valuto in linea all’interno dell’inizializzazione del mio array. Se $Debug
è true, allora quei valuesfall nel$snowSqlParam
nella posizione corretta. Lo stesso vale per la variabile $Path
.,
Semplifica operazioni complesse
È inevitabile che ti imbatti in una situazione che ha troppi confronti da controllare e la tua istruzioneIf
scorre via dal lato destro dello schermo.
Possono essere difficili da leggere e questo ti rende più incline a commettere errori. Ci sono alcune cose che possiamo fare al riguardo.
Continuazione della riga
Ci sono alcuni operatori in PowerShell che ti permettono di avvolgere il comando alla riga successiva., I logicaloperators -and
e -or
sono buoni operatori da utilizzare se si desidera interrompere l’espressione inle linee multiple.
C’è ancora molto da fare lì, ma posizionare ogni pezzo sulla propria linea fa una grande differenza.Generalmente lo uso quando ottengo più di due confronti o se devo scorrere a destra per leggere una qualsiasi delle logiche.
Pre-calcolo dei risultati
Possiamo estrarre tale istruzione dall’istruzioneif
e controllare solo il risultato.
Questo sembra molto più pulito dell’esempio precedente., Ti viene anche data l’opportunità di utilizzare il nome avariable che spiega cosa stai veramente controllando. Questo è anche un esempio di codice di auto-documentazione che salva commenti non necessari.
Più istruzioni if
Possiamo suddividere questo in più istruzioni e controllarle una alla volta. In questo caso, usiamo aflag o una variabile di tracciamento per combinare i risultati.
Ho dovuto invertire la logica per far funzionare correttamente la logica del flag. Ogni valutazione è un’istruzione if
., Il vantaggio di questo è che quando si esegue il debug, è possibile tellexactly ciò che la logica sta facendo. Sono stato in grado di aggiungere molto meglio verbosità allo stesso tempo.
L’ovvio svantaggio è che è molto più codice da scrivere. Il codice è più complesso da guardarecome prende una singola riga di logica e la esplode in 25 o più righe.
Usando le funzioni
Possiamo anche spostare tutta quella logica di convalida in una funzione. Guarda come questo sembra pulito aglance.,
if ( Test-SecureDriveConfiguration -ADUser $user ){ # do something}
Devi ancora creare la funzione per eseguire la convalida, ma rende questo codice molto più semplice con cui lavorare. Rende questo codice più facile da testare. Nei tuoi test, puoi prendere in giro la chiamata aTest-ADDriveConfiguration
e hai solo bisogno di due test per questa funzione. Uno in cui restituisce$true
e uno in cui restituisce $false
. Testare l’altra funzione è più semplice perché è cosìpiccolo.
Il corpo di quella funzione potrebbe essere ancora quel one-liner con cui abbiamo iniziato o la logica esplosa che abbiamo usato nell’ultima sezione., Questo funziona bene per entrambi gli scenari e consente di modificare facilmente thatimplementation in seguito.
Gestione degli errori
Un uso importante dell’istruzioneif
è quello di verificare le condizioni di errore prima di eseguire intoerrors. Un buon esempio è quello di verificare se una cartella esiste già prima di provare a crearla.
if ( -not (Test-Path -Path $folder) ){ New-Item -Type Directory -Path $folder}
Mi piace dire che se ti aspetti che si verifichi un’eccezione, allora non è davvero un’eccezione. Quindi controlla i tuoi valori e convalida le tue condizioni dove puoi.,
Se vuoi immergerti un po ‘ di più nella gestione effettiva delle eccezioni, ho un articolo su tutto ciò che hai sempre voluto sapere sulle eccezioni.
Parole finali
L’istruzione if
è un’istruzione così semplice ma è un pezzo fondamentale di PowerShell. You willfind te stesso utilizzando questo più volte in quasi ogni script si scrive. Spero che tu abbia una comprensione migliore di prima.