Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Nota editoriale
Importante
La specifica del linguaggio di Windows PowerShell 3.0 è stata pubblicata nel dicembre 2012 ed è basata su Windows PowerShell 3.0. Questa specifica non riflette lo stato corrente di PowerShell. Non è previsto l'aggiornamento di questa documentazione per riflettere lo stato corrente. Questa documentazione è presentata qui per riferimento cronologico.
Il documento delle specifiche è disponibile come documento di Microsoft Word dall'area download di Microsoft al seguente indirizzo: https://www.microsoft.com/download/details.aspx?id=36389 Questo documento Word è stato convertito per la presentazione qui su Microsoft Learn. Durante la conversione sono state apportate alcune modifiche editoriali per supportare la formattazione per la piattaforma Docs. Sono stati corretti alcuni errori di digitazioni e errori secondari.
8.1 Blocchi ed elenchi di istruzioni
Sintassi:
Suggerimento
La notazione ~opt~ nelle definizioni della sintassi indica che l'entità lessicale è facoltativa nella sintassi.
statement-block:
new-lines~opt~ { statement-list~opt~ new-lines~opt~ }
statement-list:
statement
statement-list statement
statement:
if-statement
label~opt~ labeled-statement
function-statement
flow-control-statement statement-terminator
trap-statement
try-statement
data-statement
inlinescript-statement
parallel-statement
sequence-statement
pipeline statement-terminator
statement-terminator:
;
new-line-character
Descrizione:
Un'istruzione specifica una sorta di azione da eseguire. Se non indicato diversamente all'interno di questa clausola, le istruzioni vengono eseguite in ordine lessicale.
Un blocco di istruzioni consente di raggruppare un set di istruzioni in una singola unità sintattica.
8.1.1 Istruzioni etichettate
Sintassi:
labeled-statement:
switch-statement
foreach-statement
for-statement
while-statement
do-statement
Descrizione:
Un'istruzione di iterazione (§8.4) o un'istruzione switch (§8.6) può essere preceduta facoltativamente da un'etichetta di istruzione, etichetta. Un'etichetta di istruzione viene usata come destinazione facoltativa di un'istruzione di interruzione (§8.5.1) o di continuazione (§8.5.2). Tuttavia, un'etichetta non modifica il flusso del controllo.
Lo spazio vuoto non è consentito tra i due punti (:) e il token che lo segue.
Esempi:
:go_here while ($j -le 100) {
# ...
}
:labelA
for ($i = 1; $i -le 5; ++$i) {
:labelB
for ($j = 1; $j -le 3; ++$j) {
:labelC
for ($k = 1; $k -le 2; ++$k) {
# ...
}
}
}
8.1.2 Valori delle dichiarazioni
Il valore di un'istruzione è l'insieme cumulativo di valori che vengono scritti nella pipeline. Se l'istruzione scrive un singolo valore scalare, quello è il valore dell'istruzione. Se l'istruzione scrive più valori, il valore dell'istruzione è il set di valori archiviati in elementi di una matrice 1 dimensionale non vincolata, nell'ordine in cui sono stati scritti. Si consideri l'esempio seguente:
$v = for ($i = 10; $i -le 5; ++$i) { }
Non sono presenti iterazioni del ciclo e non viene scritto nulla nella pipeline. Il valore dell'affermazione è $null.
$v = for ($i = 1; $i -le 5; ++$i) { }
Anche se il ciclo itera cinque volte, non viene scritto nulla nella pipeline. Il valore della dichiarazione è $null.
$v = for ($i = 1; $i -le 5; ++$i) { $i }
Il ciclo esegue l'iterazione cinque volte ogni volta che si scrive nella pipeline il int valore $i. Il valore dell'istruzione è object[] di lunghezza 5.
$v = for ($i = 1; $i -le 5; ) { ++$i }
Anche se il ciclo itera cinque volte, non viene scritto nulla nella pipeline. Il valore dell'affermazione è $null.
$v = for ($i = 1; $i -le 5; ) { (++$i) }
Il ciclo esegue l'iterazione cinque volte con ogni valore scritto nella pipeline. Il valore dell'istruzione è object[] di lunghezza 5.
$i = 1; $v = while ($i++ -lt 2) { $i }
Il ciclo scorre una volta. Il valore dell'istruzione è int con il valore di 2.
Ecco alcuni altri esempi:
# if $count is not currently defined then define it with int value 10
$count = if ($count -eq $null) { 10 } else { $count }
$i = 1
$v = while ($i -le 5) {
$i # $i is written to the pipeline
if ($i -band 1) {
"odd" # conditionally written to the pipeline
}
++$i # not written to the pipeline
}
# $v is object[], Length 8, value 1,"odd",2,3,"odd",4,5,"odd"
8.2 Istruzioni della pipeline
Sintassi:
pipeline:
assignment-expression
expression redirections~opt~ pipeline-tail~opt~
command verbatim-command-argument~opt~ pipeline-tail~opt~
assignment-expression:
expression assignment-operator statement
pipeline-tail:
| new-lines~opt~ command
| new-lines~opt~ command pipeline-tail
command:
command-name command-elements~opt~
command-invocation-operator command-module~opt~ command-name-expr command-elements~opt~
command-invocation-operator: one of
& .
command-module:
primary-expression
command-name:
generic-token
generic-token-with-subexpr
generic-token-with-subexpr:
No whitespace is allowed between ) and command-name.
generic-token-with-subexpr-start statement-list~opt~ )
command-namecommand-name-expr:
command-name
primary-expressioncommand-elements:
command-element
command-elements command-element
command-element:
command-parameter
command-argument
redirection
command-argument:
command-name-expr
verbatim-command-argument:
--% verbatim-command-argument-chars
Descrizione:
i reindirizzamenti sono descritti in §7.12; assignment-expression è descritto in §7.11; e il punto dell'operatore di chiamata del comando (.) è descritto in §3.5.5. Per una descrizione del mapping tra argomenti e parametri nelle chiamate ai comandi, vedere §8.14.
Il primo comando in una pipeline è un'espressione o una chiamata di comando. In genere, una chiamata di comando inizia con un nome di comando, che in genere è un identificatore bare. gli elementi di comando rappresentano l'elenco di argomenti al comando. Una nuova riga o un punto e virgola senza caratteri di escape termina una pipeline.
Una chiamata al comando è costituita dal nome del comando seguito da zero o più argomenti. Le regole che regolano gli argomenti sono le seguenti:
Un argomento che non è un'espressione, ma che contiene testo arbitrario con spazi bianchi non preceduti da caratteri di escape, viene trattato come se fosse racchiuso tra virgolette doppie. Le lettere maiuscole/minuscole sono conservate.
La sostituzione delle variabili e l'espansione di sottoespressione (§2.3.5.2) avviene all'interno di expandable-string-literals e expandable-here-string-literals.
Il testo all'interno delle virgolette consente di includere spazi vuoti iniziali, finali e incorporati nel valore dell'argomento. [Nota: la presenza di spazi vuoti in un argomento tra virgolette non trasforma un singolo argomento in più argomenti. nota finale]
Se si inserisce una parentesi intorno a un argomento, tale espressione viene valutata con il risultato passato anziché il testo dell'espressione originale.
Per passare un argomento simile a un parametro switch (§2.3.4), ma non è previsto come tale, racchiudere tale argomento tra virgolette.
Quando si specifica un argomento che corrisponde a un parametro con il
[switch]vincolo di tipo (§8.10.5), la presenza del nome dell'argomento in modo autonomo determina l'impostazione del parametro su$true. Tuttavia, il valore del parametro può essere impostato in modo esplicito aggiungendo un suffisso all'argomento . Ad esempio, dato un parametro vincolato di tipo p, un argomento di-p:$trueimposta p su True, mentre-p:$falseimposta p su False.Un argomento di
--indica che tutti gli argomenti che seguono devono essere passati nella loro forma effettiva, come se fossero racchiusi tra virgolette doppie.Un argomento di
--%indica che tutti gli argomenti che seguono devono essere passati con analisi ed elaborazione minime. Questo argomento è denominato parametro verbatim. Gli argomenti dopo il parametro verbatim non sono espressioni di PowerShell anche se sono espressioni di PowerShell sintatticamente valide.
Se il tipo di comando è Application, il parametro --% non viene passato al comando . Gli argomenti dopo --% espandono eventuali variabili di ambiente (stringhe racchiuse tra %). Per esempio:
echoargs.exe --% "%path%" # %path% is replaced with the value $Env:path
L'ordine di valutazione degli argomenti non è specificato.
Per informazioni sull'associazione di parametri, vedere §8.14. Per informazioni sulla ricerca dei nomi, vedere §3.8.
Al termine dell'elaborazione degli argomenti, viene richiamato il comando . Se il comando richiamato termina normalmente (§8.5.4), il controllo ripristina il punto nello script o nella funzione immediatamente dopo la chiamata al comando. Per una descrizione del comportamento relativo alla terminazione anomala, vedere break (§8.5.1), continue (§8.5.2), throw (§8.5.3), exit (§8.5.5), try (§8.7) e trap (§8.8).
In genere, un comando viene richiamato usando il nome seguito da qualsiasi argomento. È tuttavia possibile usare l'operatore di chiamata al comando , &. Se il nome del comando contiene spazi bianchi senza caratteri di escape, deve essere racchiuso tra virgolette e richiamato con questo operatore. Poiché un blocco di script non ha alcun nome, deve essere richiamato anche con questo operatore. Ad esempio, le chiamate seguenti di una chiamata Get-Factorial di comando sono equivalenti:
Get-Factorial 5
& Get-Factorial 5
& "Get-Factorial" 5
Sono consentite chiamate di funzione ricorsive dirette e indirette. Ad esempio:
function Get-Power([int]$x, [int]$y) {
if ($y -gt 0) { return $x * (Get-Power $x (--$y)) }
else { return 1 }
}
Esempi:
New-Object 'int[,]' 3,2
New-Object -ArgumentList 3,2 -TypeName 'int[,]'
dir E:\PowerShell\Scripts\*statement*.ps1 | ForEach-Object {$_.Length}
dir E:\PowerShell\Scripts\*.ps1 |
Select-String -List "catch" |
Format-Table Path, LineNumber -AutoSize
8.3 Istruzione if
Sintassi:
if-statement:
if new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block
elseif-clauses~opt~ else-clause~opt~
elseif-clauses:
elseif-clause
elseif-clauses elseif-clause
elseif-clause:
new-lines~opt~ elseif new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block
else-clause:
new-lines~opt~ else statement-block
Descrizione:
Le espressioni di controllo della pipeline devono avere un tipo bool o essere convertibili in modo implicito in tale tipo. La clausola else è facoltativa. Possono essere presenti zero o più clausole elseif.
Se la pipeline di primo livello verifica True, il blocco di istruzioni viene eseguito e l'esecuzione dell'istruzione termina. Altrimenti, se è presente una clausola elseif e la sua pipeline restituisce True, allora il blocco di istruzioni viene eseguito e l'esecuzione della condizione termina. In caso contrario, se è presente una clausola else, viene eseguito il blocco di istruzioni corrispondente.
Esempi:
$grade = 92
if ($grade -ge 90) { "Grade A" }
elseif ($grade -ge 80) { "Grade B" }
elseif ($grade -ge 70) { "Grade C" }
elseif ($grade -ge 60) { "Grade D" }
else { "Grade F" }
8.4 Istruzioni di iterazione
8.4.1 Istruzione while
Sintassi:
while-statement:
while new-lines~opt~ ( new-lines~opt~ while-condition new-lines~opt~ ) statement-block
while-condition:
new-lines~opt~ pipeline
Descrizione:
L'espressione di controllo while-condition deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente fino a quando l'espressione di controllo verifica False. L'espressione di controllo viene valutata prima di ogni esecuzione del corpo del ciclo.
Esempi:
$i = 1
while ($i -le 5) { # loop 5 times
"{0,1}`t{1,2}" -f $i, ($i*$i)
++$i
}
8.4.2 Istruzione do
Sintassi:
do-statement:
do statement-block new-lines~opt~ while new-lines~opt~ ( while-condition new-lines~opt~ )
do statement-block new-lines~opt~ until new-lines~opt~ ( while-condition new-lines~opt~ )
while-condition:
new-lines~opt~ pipeline
Descrizione:
L'espressione di controllo while-condition deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Nel formato while, il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente mentre l'espressione di controllo verifica True. Nel form until il corpo del ciclo viene eseguito ripetutamente finché l'espressione di controllo non verifica True. L'espressione di controllo viene analizzata dopo ogni esecuzione del corpo del ciclo.
Esempi:
$i = 1
do {
"{0,1}`t{1,2}" -f $i, ($i * $i)
}
while (++$i -le 5) # loop 5 times
$i = 1
do {
"{0,1}`t{1,2}" -f $i, ($i * $i)
}
until (++$i -gt 5) # loop 5 times
8.4.3 Istruzione for
Sintassi:
for-statement:
for new-lines~opt~ (
new-lines~opt~ for-initializer~opt~ statement-terminator
new-lines~opt~ for-condition~opt~ statement-terminator
new-lines~opt~ for-iterator~opt~
new-lines~opt~ ) statement-block
for new-lines~opt~ (
new-lines~opt~ for-initializer~opt~ statement-terminator
new-lines~opt~ for-condition~opt~
new-lines~opt~ ) statement-block
for new-lines~opt~ (
new-lines~opt~ for-initializer~opt~
new-lines~opt~ ) statement-block
for-initializer:
pipeline
for-condition:
pipeline
for-iterator:
pipeline
Descrizione:
L'espressione di controllo per la condizione deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente mentre l'espressione di controllo verifica True. L'espressione di controllo viene valutata prima di ogni esecuzione del corpo del ciclo.
L'espressione per inizializzatore viene valutata prima della prima valutazione dell'espressione di controllo. L'espressione per inizializzatore viene valutata solo per i suoi effetti collaterali; qualsiasi valore prodotto viene rimosso e non viene scritto nella pipeline.
L'espressione for-iterator viene valutata dopo ogni esecuzione del corpo del ciclo. L'espressione per iteratore viene valutata solo per i suoi effetti collaterali; qualsiasi valore prodotto viene rimosso e non viene scritto nella pipeline.
Se l'espressione for-condition viene omessa, l'espressione di controllo testa il valore True.
Esempi:
for ($i = 5; $i -ge 1; --$i) { # loop 5 times
"{0,1}`t{1,2}" -f $i, ($i * $i)
}
$i = 5
for (; $i -ge 1; ) { # equivalent behavior
"{0,1}`t{1,2}" -f $i, ($i * $i)
--$i
}
8.4.4 Istruzione foreach
Sintassi:
foreach-statement:
foreach new-lines~opt~ foreach-parameter~opt~ new-lines~opt~
( new-lines~opt~ variable new-lines~opt~ *in* new-lines~opt~ pipeline
new-lines~opt~ ) statement-block
foreach-parameter:
-parallel
Descrizione:
Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito per ogni elemento designato dalla variabile nella raccolta designata dalla pipeline. L'ambito della variabile non è limitato all'istruzione foreach. Di conseguenza, mantiene il valore finale al termine dell'esecuzione del corpo del ciclo. Se la pipeline designa un valore scalare (escluso il valore $null) anziché una raccolta, tale scalare viene considerato come una raccolta di un elemento. Se la pipeline designa il valore $null, la pipeline viene considerata come una raccolta di zero elementi.
Se viene specificato il foreach-parameter-parallel, il comportamento è definito dall'implementazione.
Il parametro ‑parallel è consentito solo in un flusso di lavoro (§8.10.2).
Ogni istruzione foreach ha un proprio enumeratore ($foreach§2.3.2.2, §4.5.16), che esiste solo durante l'esecuzione di tale ciclo.
Gli oggetti prodotti dalla pipeline vengono raccolti prima che l'esecuzione del blocco di istruzioni abbia inizio. Tuttavia, con il cmdlet ForEach-Object , il blocco di istruzioni viene eseguito su ogni oggetto generato.
Esempi:
$a = 10, 53, 16, -43
foreach ($e in $a) {
...
}
$e # the int value -43
foreach ($e in -5..5) {
...
}
foreach ($t in [byte], [int], [long]) {
$t::MaxValue # get static property
}
foreach ($f in Get-ChildItem *.txt) {
...
}
$h1 = @{ FirstName = "James"; LastName = "Anderson"; IDNum = 123 }
foreach ($e in $h1.Keys) {
"Key is " + $e + ", Value is " + $h1[$e]
}
8.5 Istruzioni di controllo del flusso
Sintassi:
flow-control-statement:
break label-expression~opt~
continue label-expression~opt~
throw pipeline~opt~
return pipeline~opt~
exit pipeline~opt~
label-expression:
simple-name
unary-expression
Descrizione:
Un'istruzione di controllo del flusso causa un trasferimento incondizionato del controllo in un'altra posizione.
8.5.1 Istruzione break
Descrizione:
Un'istruzione break con un'espressione label viene definita istruzione break etichettata. Un'istruzione break senza espressione etichetta viene definita istruzione break senza etichetta.
Un'istruzione break senza etichetta, direttamente all'interno di un'istruzione di iterazione (§8.4), al di fuori di un'istruzione trap termina l'esecuzione del più piccolo ciclo di iterazione racchiudente. Un'istruzione di interruzione senza etichetta direttamente all'interno di un'istruzione switch (§8.6) termina la corrispondenza dei criteri per la condizione switch-condition del commutatore corrente. Per i dettagli sull'uso del break all'interno di un'istruzione trap, vedere (§8.8).
Un'istruzione di iterazione o un'istruzione switch può essere preceduta facoltativamente da un'etichetta di istruzione (§8.1.1). Tale etichetta di istruzione può essere usata come destinazione di un'istruzione break etichettata, nel qual caso l'istruzione termina l'esecuzione dell'istruzione di iterazione di inclusione di destinazione.
Non è necessario risolvere un'interruzione etichettata in alcun ambito locale; la ricerca di un'etichetta corrispondente può continuare fino allo stack di chiamate anche attraverso i limiti di script e chiamata di funzione. Se non viene trovata alcuna etichetta corrispondente, la chiamata al comando corrente viene terminata.
Il nome dell'etichetta designata da label-expression non deve avere un valore costante.
Se label-expression è un'espressione unaria, viene convertita in una stringa.
Esempi:
$i = 1
while ($true) { # infinite loop
if ($i * $i -gt 100) {
break # break out of current while loop
}
++$i
}
$lab = "go_here"
:go_here
for ($i = 1; ; ++$i) {
if ($i * $i -gt 50) {
break $lab # use a string value as target
}
}
:labelA
for ($i = 1; $i -le 2; $i++) {
:labelB
for ($j = 1; $j -le 2; $j++) {
:labelC
for ($k = 1; $k -le 3; $k++) {
if (...) { break labelA }
}
}
}
8.5.2 Istruzione continue
Descrizione:
Un'istruzione continue con un'espressione etichettata viene definita un'istruzione continue etichettata. Un'istruzione continue senza un'espressione di etichetta viene definita istruzione continue senza etichetta.
L'uso di continue all'interno di una trap dichiarazione è descritto in §8.8.
continue Un'istruzione senza etichetta all'interno di un ciclo interrompe l'esecuzione del ciclo corrente e trasferisce il controllo alla parentesi graffa di chiusura dell'istruzione di iterazione più interna racchiusa (§8.4).
continue Un'istruzione senza etichetta all'interno di un commutatore termina l'esecuzione dell'iterazione corrente switch e trasferisce il controllo alla switch più piccola che racchiude (§8.6).
Un'istruzione di iterazione o un'istruzione switch (§8.6) può essere preceduta facoltativamente da un'etichetta di istruzione (§8.1.1). Tale etichetta di istruzione può essere usata come destinazione di un'istruzione etichettata racchiusa continue, nel qual caso l'istruzione termina l'esecuzione del ciclo o switch dell'iterazione corrente e trasferisce il controllo all'etichetta dell'iterazione o istruzione racchiusa di destinazione switch.
Non è necessario risolvere un oggetto etichettato continue in alcun ambito locale. La ricerca di un'etichetta corrispondente può comportare continue l'aumento dello stack di chiamate anche attraverso i limiti di script e chiamata di funzione. Se non viene trovata alcuna etichetta corrispondente, la chiamata al comando corrente viene terminata.
Il nome dell'etichetta designata da label-expression non deve avere un valore costante.
Se label-expression è un'espressione unaria, viene convertita in una stringa.
Esempi:
$i = 1
while (...) {
...
if (...) {
continue # start next iteration of current loop
}
...
}
$lab = "go_here"
:go_here
for (...; ...; ...) {
if (...) {
continue $lab # start next iteration of labeled loop
}
}
:labelA
for ($i = 1; $i -le 2; $i++) {
:labelB
for ($j = 1; $j -le 2; $j++) {
:labelC
for ($k = 1; $k -le 3; $k++) {
if (...) { continue labelB }
}
}
}
8.5.3 Istruzione throw
Descrizione:
Un'eccezione è un modo per gestire una condizione di errore a livello di sistema o di applicazione. L'istruzione throw genera un'eccezione. Per informazioni sulla gestione delle eccezioni, vedere il paragrafo 8.7 .
Se la pipeline viene omessa e l'istruzione throw non si trova in una clausola catch, il comportamento è definito dall'implementazione. Se la pipeline è presente e l'istruzione throw si trova in una clausola catch, l'eccezione intercettata da tale clausola catch viene generata nuovamente dopo l'esecuzione di qualsiasi clausola finally associata alla clausola catch .
Se la pipeline è presente, il tipo dell'eccezione generata è definito dall'implementazione.
Quando viene generata un'eccezione, il controllo viene trasferito alla prima clausola catch in un'istruzione try che può gestire l'eccezione. La posizione in cui viene generata l'eccezione inizialmente viene chiamata punto di generazione. Una volta generata un'eccezione, i passaggi descritti in §8.7 vengono eseguiti ripetutamente fino a quando non viene trovata una clausola catch corrispondente all'eccezione o non è possibile trovare nessuna.
Esempi:
throw
throw 100
throw "No such record in file"
Se la pipeline viene omessa e l'istruzione throw non si trova all'interno di una clausola catch, il testo "ScriptHalted" viene scritto nella pipeline e il tipo dell'eccezione generata è System.Management.Automation.RuntimeException.
Se la pipeline è presente, l'eccezione generata viene incapsulata in un oggetto di tipo System.Management.Automation.RuntimeException, che include informazioni sull'eccezione sotto forma di oggetto System.Management.Automation.ErrorRecord (accessibile tramite $_).
Esempio 1: throw 123 genera un'eccezione di tipo RuntimeException. Dall'interno del blocco catch, $_.TargetObject contiene l'oggetto contenente, in questo caso un oggetto System.Int32 con valore 123.
Esempio 2: throw "xxx" genera un'eccezione di tipo RuntimeException. Dall'interno del blocco $_.TargetObject catch, contiene l'oggetto di cui è stato eseguito il wrapping all'interno, in questo caso, un System.String oggetto con valore "xxx".
Esempio 3: throw 10,20 genera un'eccezione di tipo RuntimeException. Dall'interno del blocco catch, $_.TargetObject contiene l'oggetto di cui è stato eseguito il wrapping, in questo caso, una matrice non vincolata di due elementi con i valori System.Object[].Int32` 10 e 20.
8.5.4 Istruzione di ritorno
Descrizione:
L'istruzione return scrive nella pipeline i valori designati dalla pipeline, se presenti, e restituisce il controllo al chiamante della funzione o dello script. Una funzione o uno script può avere zero o più return istruzioni.
Se l'esecuzione raggiunge la parentesi graffa di chiusura di una funzione, si assume un return implicito senza pipeline.
L'istruzione return è un po ' di "zucchero sintattico" per consentire ai programmatori di esprimersi come possono in altri linguaggi. Tuttavia, il valore restituito da una funzione o uno script è in realtà tutti i valori scritti nella pipeline da tale funzione o script più qualsiasi valore specificato dalla pipeline. Se nella pipeline viene scritto solo un valore scalare, il tipo è il tipo del valore restituito; in caso contrario, il tipo restituito è una matrice un-dimensionale senza vincoli contenente tutti i valori scritti nella pipeline.
Esempi:
function Get-Factorial ($v) {
if ($v -eq 1) {
return 1 # return is not optional
}
return $v * (Get-Factorial ($v - 1)) # return is optional
}
Al chiamante di Get-Factorial viene restituito un int.
function Test {
"text1" # "text1" is written to the pipeline
# ...
"text2" # "text2" is written to the pipeline
# ...
return 123 # 123 is written to the pipeline
}
Il chiamante per Test tornare a una matrice 1 dimensionale senza vincoli di tre elementi.
8.5.5 Istruzione exit
Descrizione:
L'istruzione exit termina lo script corrente e restituisce il controllo e un codice di uscita all'ambiente host o allo script chiamante. Se viene specificata la pipeline , il valore designato viene convertito in int, se necessario. Se non esiste alcuna conversione di questo tipo o se la pipeline viene omessa, viene restituito il valore int zero.
Esempi:
exit $count # terminate the script with some accumulated count
8.6 Istruzione switch
Sintassi:
switch-statement:
switch new-lines~opt~ switch-parameters~opt~ switch-condition switch-body
switch-parameters:
switch-parameter
switch-parameters switch-parameter
switch-parameter:
-Regex
-Wildcard
-Exact
-CaseSensitive
-Parallel
switch-condition:
( new-lines~opt~ pipeline new-lines~opt~ )
-File new-lines~opt~ switch-filename
switch-filename:
command-argument
primary-expression
switch-body:
new-lines~opt~ { new-lines~opt~ switch-clauses }
switch-clauses:
switch-clause
switch-clauses switch-clause
switch-clause:
switch-clause-condition statement-block statement-terimators~opt~
switch-clause-condition:
command-argument
primary-expression
Descrizione:
Se la condizione switch designa un singolo valore, il controllo viene passato a uno o più blocchi di istruzioni dei criteri di ricerca corrispondenti. Se nessun criterio corrisponde, è possibile eseguire alcune azioni predefinite.
Un switch deve contenere una o più clausole switch, ciascuna delle quali inizia con un criterio (una clausola switch non predefinita) o la parola chiave default (una clausola switch predefinita). Un interruttore deve contenere zero o una default clausola di caso, e zero o più clausole di caso non predefinite. Le clausole switch possono essere scritte in qualsiasi ordine.
Più modelli possono avere lo stesso valore. Un modello non deve essere un valore letterale e un'opzione può avere modelli con tipi diversi.
Se il valore di switch-condition corrisponde a un valore del criterio, viene eseguito il blocco di istruzioni del criterio. Se più valori del criterio corrispondono al valore di switch-condition, viene eseguito il blocco di istruzioni di ogni criterio corrispondente, in ordine lessicale, a meno che uno di questi blocchi di istruzioninon contenga un'istruzione break (§8.5.1).
Se il valore di condizione switch non corrisponde a nessun valore del modello, se esiste una default clausola switch, viene eseguito il relativo blocco di istruzioni; in caso contrario, la corrispondenza di modelli per tale condizione switch viene conclusa.
I commutatori possono essere annidati, con ogni commutatore che ha un proprio set di clausole switch. In questi casi, una clausola switch appartiene al commutatore più interno attualmente nell'ambito.
All'ingresso di ogni blocco di istruzioni, viene automaticamente assegnato il valore della $_ che ha causato il passaggio del controllo a quel blocco di istruzioni.
$_è disponibile anche nella condizione switch-clause-condition del blocco di istruzioni.
La corrispondenza degli elementi non-stringhe viene eseguita verificando l'uguaglianza (§7.8.1).
Se la corrispondenza include le stringhe, per impostazione predefinita, il confronto è case-insensitive. La presenza del parametro switch-CaseSensitive rende il confronto sensibile alle maiuscole e minuscole.
Un criterio può contenere caratteri jolly (§3.15), nel qual caso vengono eseguiti confronti di stringhe usando i caratteri jolly, ma solo se è presente il parametro di switch-Wildcard. Per impostazione predefinita, il confronto non fa distinzione tra maiuscole e minuscole.
Un modello può contenere un'espressione regolare (§3.16), nel qual caso vengono effettuati confronti tra stringhe con espressioni regolari, ma solo se il parametro switch-Regex è presente. Per impostazione predefinita, il confronto non fa distinzione tra maiuscole e minuscole. Se -Regex è presente e viene trovata una corrispondenza con un criterio, $Matches viene definito nel blocco di istruzionidella clausola switch per tale criterio.
Un parametro switch può essere abbreviato; è possibile usare qualsiasi parte iniziale distinta di un parametro. Ad esempio, ‑Regex, ‑Rege‑Reg, , ‑Ree ‑R sono equivalenti.
Se vengono specificati parametri switch-parameterin conflitto, prevale quello lessicalmente finale. La presenza di ‑Exact disabilita -Regex e -Wildcard; non ha alcun effetto su ‑Case, tuttavia.
Se si specifica il parametro‑Parallel switch, il comportamento è definito dall'implementazione.
Il switch-parameter‑Parallel è consentito solo in un flusso di lavoro (§8.10.2).
Se un criterio è un'espressione di blocco di script, tale blocco viene valutato e il risultato viene convertito in bool, se necessario. Se il risultato ha il valore $true, viene eseguito il blocco di istruzioni corrispondente; in caso contrario, non viene eseguito.
Se switch-condition definisce più valori, l'opzione viene applicata a ogni valore in ordine lessicale usando le regole descritte in precedenza per una condizione switch che designa un singolo valore. Ogni istruzione switch ha un proprio enumeratore ($switch§2.3.2.2, §4.5.16), che esiste solo durante l'esecuzione di tale opzione.
Un'istruzione switch può avere un'etichetta e può contenere istruzioni di interruzione etichettate e non etichettate (§8.5.1) e continue (§8.5.2).
Se switch-condition è -Fileswitch-filename, invece di scorrere i valori in un'espressione, l'istruzione switch itera sui valori nel file designato da switch-filename. Il file viene letto una riga alla volta, ciascuna contenente un valore. I caratteri di terminazione riga non sono inclusi nei valori.
Esempi:
$s = "ABC def`nghi`tjkl`fmno @#$"
$charCount = 0; $pageCount = 0; $lineCount = 0; $otherCount = 0
for ($i = 0; $i -lt $s.Length; ++$i) {
++$charCount
switch ($s[$i]) {
"`n" { ++$lineCount }
"`f" { ++$pageCount }
"`t" { }
" " { }
default { ++$otherCount }
}
}
switch -Wildcard ("abc") {
a* { "a*, $_" }
?B? { "?B? , $_" }
default { "default, $_" }
}
switch -Regex -CaseSensitive ("abc") {
^a* { "a*" }
^A* { "A*" }
}
switch (0, 1, 19, 20, 21) {
{ $_ -lt 20 } { "-lt 20" }
{ $_ -band 1 } { "Odd" }
{ $_ -eq 19 } { "-eq 19" }
default { "default" }
}
8.7 Istruzione try/finally
Sintassi:
try-statement:
try statement-block catch-clauses
try statement-block finally-clause
try statement-block catch-clauses finally-clause
catch-clauses:
catch-clause
catch-clauses catch-clause
catch-clause:
new-lines~opt~ catch catch-type-list~opt~
statement-block
catch-type-list:
new-lines~opt~ type-literal
catch-type-list new-lines~opt~ , new-lines~opt~
type-literalfinally-clause:
new-lines~opt~ finally statement-block
Descrizione:
L'istruzione try fornisce un meccanismo per gestire le eccezioni che si verificano durante l'esecuzione di un blocco. L'istruzione try consente inoltre di specificare un blocco di codice che viene sempre eseguito quando il controllo lascia l'istruzione try. Il processo di generazione di un'eccezione tramite l'istruzione throw è descritto in §8.5.3.
Un blocco try è il blocco di istruzioni associato all'istruzione try. Un blocco catch è il blocco di istruzioni associato a una clausola catch. Un blocco finally è il blocco di istruzioni associato a una clausola finally.
Una clausola catch senza un elenco tipi di catch è detta clausola catch generale.
Ogni clausola catch è un gestore di eccezioni e una clausola catch, il cui elenco di tipi di catch contiene il tipo dell'eccezione generata, è una clausola catch corrispondente. Una clausola catch generale corrisponde a tutti i tipi di eccezione.
Sebbene le clausole catch e finally-clause siano facoltative, almeno una di esse deve essere presente.
La gestione di un'eccezione lanciata consiste nella valutazione ripetuta dei passaggi successivi fino a trovare una clausola catch corrispondente all'eccezione.
Nell'ambito corrente viene esaminata ogni istruzione try che racchiude il punto di lancio. Per ogni istruzione try S, a partire dall'istruzione try più interna e che termina con l'istruzione try più esterna, vengono valutati i passaggi seguenti:
Se il
tryblocco di S racchiude il punto di lancio e se S ha una o più clausole catch, le clausole catch vengono esaminate in ordine lessicale per individuare un gestore appropriato per l'eccezione. La prima clausola catch che specifica il tipo di eccezione o un tipo di base del tipo di eccezione viene considerata valida. Una clausola catch generale è considerata compatibile con ogni tipo di eccezione. Se si trova una clausola catch corrispondente, l'elaborazione delle eccezioni viene completata trasferendo il controllo al blocco di tale clausola catch. All'interno di una clausola catch corrispondente, la variabile$_contiene una descrizione dell'eccezione corrente.In caso contrario, se il blocco
tryo un bloccocatchdi S racchiude il punto di lancio e se S ha un bloccofinally, il controllo viene trasferito al blocco finally. Se ilfinallyblocco genera un'altra eccezione, l'elaborazione dell'eccezione corrente viene terminata. In caso contrario, quando il controllo raggiunge la fine delfinallyblocco, l'elaborazione dell'eccezione corrente viene continuata.
Se un gestore di eccezioni non si trova nell'ambito corrente, i passaggi precedenti vengono ripetuti per l'ambito circostante, con un punto di lancio corrispondente all'istruzione da cui è stato richiamato l'ambito corrente.
Se l'elaborazione delle eccezioni termina tutti gli ambiti, a indicare che non esiste alcun gestore per l'eccezione, il comportamento non viene specificato.
Per evitare clausole catch non raggiungibili in un blocco try, una clausola catch potrebbe non specificare un tipo di eccezione uguale o derivato da un tipo specificato in una clausola catch precedente all'interno dello stesso blocco try.
Le istruzioni di un finally blocco vengono sempre eseguite quando il controllo lascia un'istruzione try . Ciò vale se il trasferimento del controllo si verifica come risultato della normale esecuzione, in seguito all'esecuzione di un'istruzione break, continueo return come risultato di un'eccezione generata dall'istruzione try .
Se viene lanciata un'eccezione durante l'esecuzione di un finally blocco, l'eccezione viene lanciata alla successiva istruzione contenitore try. Se è in corso la gestione di un'altra eccezione, l'eccezione viene persa. Il processo di generazione di un'eccezione viene ulteriormente illustrato nella descrizione dell'istruzione throw .
try le istruzioni possono coesistere con trap le istruzioni. Per informazioni dettagliate, vedere §8.8 .
Esempi:
$a = New-Object 'int[]' 10
$i = 20 # out-of-bounds subscript
while ($true) {
try {
$a[$i] = 10
"Assignment completed without error"
break
}
catch [IndexOutOfRangeException] {
"Handling out-of-bounds index, >$_<`n"
$i = 5
}
catch {
"Caught unexpected exception"
}
finally {
# ...
}
}
Ogni eccezione lanciata viene sollevata come System.Management.Automation.RuntimeException. Se nel blocco sono presenti clausole tryspecifiche del tipo, la proprietà InnerException dell'eccezione viene controllata per provare a trovare una corrispondenza, ad esempio con il tipo System.IndexOutOfRangeException precedente.
8.8 L'istruzione trap
Sintassi:
trap-statement:
*trap* new-lines~opt~ type-literal~opt~ new-lines~opt~ statement-block
Descrizione:
Un'istruzione trap con e senza valore letterale di tipo è analoga a un catch blocco (§8.7) rispettivamente con e senza catch-type-list, ad eccezione del fatto che un'istruzione trap può intercettare un solo tipo alla volta.
È possibile definire più trap istruzioni nello stesso blocco di istruzioni e il relativo ordine di definizione è irrilevante. Se due trap istruzioni con lo stesso tipo-letterale sono definite nello stesso ambito, la prima viene usata per elaborare un'eccezione di tipo corrispondente.
A differenza di un catch blocco, un'istruzione trap corrisponde esattamente a un tipo di eccezione. Non viene eseguita alcuna corrispondenza tra tipi derivati.
Quando si verifica un'eccezione, se nell'ambito corrente non è presente alcuna istruzione corrispondente trap, viene eseguita una ricerca di un'istruzione trap corrispondente nell'ambito circostante, che può comportare la ricerca nello script chiamante, nella funzione o nel filtro, e quindi nel relativo chiamante e così via. Se la ricerca termina tutti gli ambiti, indicando che non esiste alcun gestore per l'eccezione, il comportamento è indefinito.
Il trap di un'istruzione viene eseguito solo per elaborare l'eccezione corrispondente. In caso contrario, l'esecuzione passa su di essa.
Se il trapcorpo dell'istruzione viene chiuso normalmente, per impostazione predefinita, un oggetto errore viene scritto nel flusso di errore, l'eccezione viene considerata gestita e l'esecuzione continua con l'istruzione immediatamente successiva a quella nell'ambito contenente l'istruzione che ha reso visibile l'eccezionetrap. La causa dell'eccezione potrebbe trovarsi in un comando chiamato dal comando contenente l'istruzione trap .
Se l'istruzione finale eseguita in un trapcorpo dell'istruzione è continua (§8.5.2), la scrittura dell'oggetto errore nel flusso di errore viene eliminata e l'esecuzione continua con l'istruzione immediatamente successiva a quella nell'ambito contenente l'istruzione trap che ha reso visibile l'eccezione. Se l'istruzione finale eseguita in un trapcorpo dell'istruzione è break (§8.5.1), la scrittura dell'oggetto errore nel flusso di errore viene eliminata e l'eccezione viene generata nuovamente.
All'interno di un'istruzione trap la variabile $_ contiene una descrizione dell'errore corrente.
Si consideri il caso in cui un'eccezione generata dall'interno di un blocco try non dispone di un blocco catch corrispondente, ma esiste a un livello di blocco superiore un'istruzione trap corrispondente. Dopo l'esecuzione della clausola finally del blocco try, l'istruzione trap ottiene il controllo anche se un ambito padre ha un blocco corrispondente catch. Se un'istruzione trap viene definita nel blocco try stesso e il blocco try ha un blocco catch corrispondente, l'istruzione trap assume il controllo.
Esempi:
Nell'esempio seguente, l'oggetto errore viene registrato. L'esecuzione continua con l'istruzione immediatamente successiva a quella che ha causato la trap; il messaggio "Done" viene scritto nella pipeline.
$j = 0; $v = 10/$j; "Done"
trap { $j = 2 }
Nell'esempio seguente, la scrittura dell'oggetto errore viene eliminata e l'esecuzione continua con l'istruzione immediatamente successiva a quella che ha causato la trap; ovvero "Done" viene scritto nella pipeline.
$j = 0; $v = 10/$j; "Done"
trap { $j = 2; continue }
Nell'esempio seguente la scrittura dell'oggetto errore viene eliminata e viene generata nuovamente l'eccezione.
$j = 0; $v = 10/$j; "Done"
trap { $j = 2; break }
Nell'esempio seguente, le istruzioni 'trap' e quelle di generazione di eccezioni si trovano nello stesso ambito. Dopo che l'eccezione viene intercettata e gestita, l'esecuzione riprende con la scrittura di 1 nella pipeline.
&{trap{}; throw '\...'; 1}
Nell'esempio seguente le istruzioni trap e di generazione di eccezioni si trovano in ambiti diversi. Dopo che l'eccezione viene intercettata e gestita, l'esecuzione riprende con la scrittura di 2 (non 1) nella pipeline.
trap{} &{throw '\...'; 1}; 2
8.9 Istruzione dati
Sintassi:
data-statement:
data new-lines~opt~ data-name data-commands-allowed~opt~ statement-block
data-name:
simple-name
data-commands-allowed:
new-lines~opt~ -SupportedCommand data-commands-list
data-commands-list:
new-lines~opt~ data-command
data-commands-list , new-lines~opt~ data-command
data-command:
command-name-expr
Descrizione:
Un'istruzione dati crea una sezione di dati, mantenendo i dati di tale sezione separati dal codice. Questa separazione supporta funzionalità come file di risorse di stringa separati per il testo, ad esempio messaggi di errore e stringhe della Guida. Consente inoltre di supportare l'internazionalizzazione semplificando l'isolamento, l'individuazione e l'elaborazione di stringhe che verranno tradotte in lingue diverse.
Uno script o una funzione può avere zero o più sezioni di dati.
Il blocco di istruzioni di una sezione di dati è limitato a contenere solo le funzionalità di PowerShell seguenti:
- Tutti gli operatori tranne
-match - Istruzione
if - Le variabili automatiche seguenti:
$PSCulture,$PSUICulture$true, ,$falsee$null. - Commenti
- Le pipeline
- Dichiarazioni separate da punti e virgola (
;) - Valori letterali
- Chiamate del cmdlet ConvertFrom-StringData
- Qualsiasi altro cmdlet identificato tramite il parametro SupportedCommand
Se viene utilizzato il cmdlet ConvertFrom-StringData, le coppie chiave/valore possono essere espresse usando qualsiasi forma di stringa letterale. Tuttavia, expandable-string-literals e expandable-here-string-literals non deve contenere sostituzioni di variabili o espansioni di sottoespressione.
Esempi:
Il parametro SupportedCommand indica che i cmdlet o le funzioni specificati generano solo dati.
Ad esempio, la sezione dati seguente include un cmdlet scritto dall'utente, ConvertTo-Xml, che formatta i dati in un file XML:
data -SupportedCommand ConvertTo-Xml {
Format-Xml -Strings string1, string2, string3
}
Si consideri l'esempio seguente, in cui la sezione dati contiene un ConvertFrom-StringData comando che converte le stringhe in una tabella hash, il cui valore è assegnato a $messages.
$messages = data {
ConvertFrom-StringData -StringData @'
Greeting = Hello
Yes = yes
No = no
'@
}
Le chiavi e i valori della tabella hash sono accessibili rispettivamente usando $messages.Greeting, $messages.Yese $messages.No.
È ora possibile salvarlo come risorsa in lingua inglese. Le risorse in lingua tedesca e spagnola possono essere create in file separati, con le sezioni di dati seguenti:
$messages = data {
ConvertFrom-StringData -StringData @"
Greeting = Guten Tag
Yes = ja
No = nein
"@
}
$messagesS = data {
ConvertFrom-StringData -StringData @"
Greeting = Buenos días
Yes = sí
No = no
"@
}
Se dataname è presente, denomina la variabile (senza usare un carattere iniziale $) in cui deve essere archiviato il valore dell'istruzione dati. In particolare, $name = data { ... } è equivalente a data name { ... }.
8.10 Definizioni di funzione
Sintassi:
function-statement:
function new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
filter new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
workflow new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
function-name:
command-argument
command-argument:
command-name-expr
function-parameter-declaration:
new-lines~opt~ ( parameter-list new-lines~opt~ )
parameter-list:
script-parameter
parameter-list new-lines~opt~ , script-parameter
script-parameter:
new-lines~opt~ attribute-list~opt~ new-lines~opt~ variable script-parameter-default~opt~
script-block:
param-block~opt~ statement-terminators~opt~ script-block-body~opt~
param-block:
new-lines~opt~ attribute-list~opt~ new-lines~opt~ param new-lines~opt~
( parameter-list~opt~ new-lines~opt~ )
parameter-list:
script-parameter
parameter-list new-lines~opt~ , script-parameter
script-parameter-default:
new-lines~opt~ = new-lines~opt~ expression
script-block-body:
named-block-list
statement-list
named-block-list:
named-block
named-block-list named-block
named-block:
block-name statement-block statement-terminators~opt~
block-name: one of
dynamicparam begin process end
Descrizione:
Una definizione di funzione specifica il nome della funzione, del filtro o del flusso di lavoro da definire e i nomi dei relativi parametri, se presenti. Contiene anche zero o più istruzioni eseguite per ottenere lo scopo di tale funzione.
Ogni funzione è un'istanza della classe System.Management.Automation.FunctionInfo.
8.10.1 Funzioni di filtro
Mentre una funzione normale viene eseguita una volta in una pipeline e accede alla raccolta di input tramite $input, un filtro è un tipo speciale di funzione che viene eseguito una volta per ogni oggetto nella raccolta di input.
L'oggetto attualmente in fase di elaborazione è disponibile tramite la variabile $_.
Un filtro senza blocchi denominati (§8.10.7) equivale a una funzione con un blocco di processo, ma senza blocco iniziale o finale.
Si consideri la definizione e le chiamate della funzione di filtro seguenti:
filter Get-Square2 { # make the function a filter
$_ * $_ # access current object from the collection
}
-3..3 | Get-Square2 # collection has 7 elements
6, 10, -3 | Get-Square2 # collection has 3 elements
Ogni filtro è un'istanza della classe System.Management.Automation.FilterInfo (§4.5.11).
8.10.2 Funzioni del flusso di lavoro
Una funzione del flusso di lavoro è simile a una funzione comune con semantica definita dall'implementazione. Una funzione del flusso di lavoro viene convertita in una sequenza di attività di Windows Workflow Foundation ed eseguita nel motore windows Workflow Foundation.
8.10.3 Elaborazione degli argomenti
Si consideri la definizione seguente per una funzione denominata Get-Power:
function Get-Power ([long]$Base, [int]$Exponent) {
$result = 1
for ($i = 1; $i -le $Exponent; ++$i) {
$result *= $Base
}
return $result
}
Questa funzione ha due parametri, $Base e $Exponent. Contiene anche un set di istruzioni che, per valori esponenti $Base^$Exponent^ non negativi, calcola e restituisce il risultato al Get-Powerchiamante.
Quando un script, una funzione o un filtro inizia l'esecuzione, ogni parametro viene inizializzato sul valore dell'argomento corrispondente. Se non è presente alcun argomento corrispondente e viene fornito un valore predefinito (§8.10.4), tale valore viene utilizzato; in caso contrario, viene usato il valore $null . Di conseguenza, ogni parametro è una nuova variabile come se fosse inizializzata dall'assegnazione all'inizio del blocco di script.
Se un parametro script contiene un vincolo di tipo, come [long] e [int] sopra, il valore dell'argomento corrispondente viene convertito in tale tipo, se necessario; altrimenti, non si verifica alcuna conversione.
Quando un script, una funzione o un filtro inizia l'esecuzione, la variabile $args viene definita all'interno di essa come matrice un-dimensionale senza vincoli, che contiene tutti gli argomenti non associati per nome o posizione, in ordine lessicale.
Si consideri la definizione e le chiamate di funzione seguenti:
function F ($a, $b, $c, $d) { ... }
F -b 3 -d 5 2 4 # $a is 2, $b is 3, $c is 4, $d is 5, $args Length 0
F -a 2 -d 3 4 5 # $a is 2, $b is 4, $c is 5, $d is 3, $args Length 0
F 2 3 4 5 -c 7 -a 1 # $a is 1, $b is 2, $c is 7, $d is 3, $args Length 2
Per altre informazioni sull'associazione di parametri, vedere §8.14.
8.10.4 Inizializzatori di parametri
La dichiarazione di un parametro p può contenere un inizializzatore, nel qual caso il valore dell'inizializzatore viene usato per inizializzare p provided p non è associato ad alcun argomento nella chiamata.
Si consideri la definizione e le chiamate di funzione seguenti:
function Find-Str ([string]$Str, [int]$StartPos = 0) { ... }
Find-Str "abcabc" # 2nd argument omitted, 0 used for $StartPos
Find-Str "abcabc" 2 # 2nd argument present, so it is used for $StartPos
8.10.5 Vincolo di tipo [switch]
Quando viene passato un parametro switch, il parametro corrispondente nel comando deve essere limitato dal switch di tipo specificato. L'opzione di tipo ha due valori, True e False.
Si consideri la definizione e le chiamate di funzione seguenti:
function Process ([switch]$Trace, $P1, $P2) { ... }
Process 10 20 # $Trace is False, $P1 is 10, $P2 is 20
Process 10 -Trace 20 # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$false # $Trace is False, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$true # $Trace is True, $P1 is 10, $P2 is 20
8.10.6 Pipeline e funzioni
Quando uno script, una funzione o un filtro viene usato in una pipeline, una raccolta di valori viene recapitata a tale script o funzione. Lo script, la funzione o il filtro ottiene l'accesso a tale raccolta tramite l'enumeratore $input (§2.3.2.2, §4.5.16), definito all'immissione di tale script, funzione o filtro.
Si consideri la definizione e le chiamate di funzione seguenti:
function Get-Square1 {
foreach ($i in $input) { # iterate over the collection
$i * $i
}
}
-3..3 | Get-Square1 # collection has 7 elements
6, 10, -3 | Get-Square1 # collection has 3 elements
8.10.7 Blocchi denominati
Le istruzioni all'interno di un blocco di script possono appartenere a un blocco senza nome di grandi dimensioni oppure possono essere distribuite in uno o più blocchi denominati. I blocchi denominati consentono l'elaborazione personalizzata delle raccolte provenienti da pipeline; I blocchi denominati possono essere definiti in qualsiasi ordine.
Le istruzioni in un blocco di inizio (ad esempio, una contrassegnata con la parola chiave begin) vengono eseguite una sola volta, prima che venga recapitato il primo oggetto pipeline.
Le istruzioni in un blocco di processo (ad esempio, una contrassegnata con il processo di parola chiave) vengono eseguite per ogni oggetto pipeline recapitato. ($_ fornisce l'accesso all'oggetto corrente elaborato dalla raccolta di input proveniente dalla pipeline. Ciò significa che se una raccolta di zero elementi viene inviata tramite la pipeline, il blocco di processo non viene eseguito affatto. Tuttavia, se lo script o la funzione viene chiamato all'esterno di un contesto della pipeline, questo blocco viene eseguito esattamente una volta e $_ viene impostato su $null, perché non è presente alcun oggetto raccolta corrente.
Le istruzioni in un blocco di fine (ad esempio, una contrassegnata con la parola chiave end) vengono eseguite una sola volta, dopo il recapito dell'ultimo oggetto pipeline.
Blocco dynamicparam 8.10.8
Le sottosezioni di §8.10 finora gestiscono parametri statici, definiti come parte del codice sorgente. È anche possibile definire parametri dinamici tramite un blocco dynamicparam, un'altra forma di blocco denominato (§8.10.7), contrassegnata con la parola chiave dynamicparam. Gran parte di questo macchinario è definita dall'implementazione.
I parametri dinamici sono parametri di un cmdlet, di una funzione, di un filtro o di uno script disponibili solo in determinate condizioni. Un caso di questo tipo è il parametro Encoding del Set-Item cmdlet.
Nel blocco di istruzioni usare un'istruzione if per specificare le condizioni in cui il parametro è disponibile nella funzione. Usare il cmdlet New-Object per creare un oggetto di un tipo definito dall'implementazione per rappresentare il parametro e specificarne il nome.
New-Object Usare anche per creare un oggetto di un tipo diverso definito dall'implementazione per rappresentare gli attributi definiti dall'implementazione del parametro.
L'esempio seguente mostra una funzione con parametri standard denominati Name e Path e un parametro dinamico facoltativo denominato DP1. Il parametro DP1 si trova nel set di parametri PSet1 e ha un tipo di Int32. Il parametro DP1 è disponibile nella funzione Sample solo quando il valore del parametro Path contiene "HKLM:", a indicare che viene usato nell'unità HKEY_LOCAL_MACHINE del Registro di sistema.
function Sample {
param ([string]$Name, [string]$Path)
dynamicparam {
if ($Path -match "*HKLM*:") {
$dynParam1 = New-Object System.Management.Automation.RuntimeDefinedParameter("dp1", [int32], $attributeCollection)
$attributes = New-Object System.Management.Automation.ParameterAttribute
$attributes.ParameterSetName = 'pset1'
$attributes.Mandatory = $false
$attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection``1[System.Attribute]
$attributeCollection.Add($attributes)
$paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$paramDictionary.Add("dp1", $dynParam1)
return $paramDictionary
}
}
}
Il tipo utilizzato per creare un oggetto per rappresentare un parametro dinamico è System.Management.Automation.RuntimeDefinedParameter.
Il tipo utilizzato per creare un oggetto per rappresentare gli attributi del parametro è System.Management.Automation.ParameterAttribute.
Gli attributi definiti dall'implementazione del parametro includono Mandatory, Position e ValueFromPipeline.
Blocco param 8.10.9
Un blocco param fornisce un modo alternativo per dichiarare i parametri. Ad esempio, i set di dichiarazioni di parametri seguenti sono equivalenti:
function FindStr1 ([string]$Str, [int]$StartPos = 0) { ... }
function FindStr2 {
param ([string]$Str, [int]$StartPos = 0) ...
}
Un param-block consente una lista-di-attributi nel param-block mentre una dichiarazione-di-parametri-di-funzione non lo fa.
Uno script può avere un blocco parametri ma non una dichiarazione-parametro-funzione. Una definizione di funzione o filtro può avere una dichiarazione di parametro funzione o un blocco di parametri, ma non tutti e due.
Si consideri l'esempio seguente:
param ( [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
[string[]] $ComputerName )
Il parametro , $ComputerName, ha il tipo string[], è obbligatorio e accetta l'input dalla pipeline.
Per una descrizione dell'attributo Parameter e per altri esempi, vedere §12.3.7.
8.11 La dichiarazione parallela
Sintassi:
parallel-statement:
*parallel* statement-block
L'istruzione parallela contiene zero o più istruzioni eseguite in modo definito dall'implementazione.
Un'istruzione parallela è consentita solo in un flusso di lavoro (§8.10.2).
8.12 Istruzione di sequenza
Sintassi:
sequence-statement:
*sequence* statement-block
L'istruzione sequence contiene zero o più istruzioni eseguite in modo definito dall'implementazione.
Un'istruzione di sequenza è consentita solo all'interno di un processo (§8.10.2).
8.13 Istruzione inlinescript
Sintassi:
inlinescript-statement:
inlinescript statement-block
L'istruzione inlinescript contiene zero o più istruzioni eseguite in modo definito dall'implementazione.
Un'istruzione inlinescript è consentita solo in un flusso di lavoro (§8.10.2).
8.14 Associazione di parametri
Quando viene richiamato uno script, una funzione, un filtro o un cmdlet, ogni argomento può essere associato al parametro corrispondente in base alla posizione, con il primo parametro con posizione zero.
Si consideri il frammento di definizione seguente per una funzione denominata Get-Powere le chiamate:
function Get-Power ([long]$Base, [int]$Exponent) { ... }
Get-Power 5 3 # argument 5 is bound to parameter $Base in position 0
# argument 3 is bound to parameter $Exponent in position 1
# no conversion is needed, and the result is 5 to the power 3
Get-Power 4.7 3.2 # double argument 4.7 is rounded to int 5, double argument
# 3.2 is rounded to int 3, and result is 5 to the power 3
Get-Power 5 # $Exponent has value $null, which is converted to int 0
Get-Power # both parameters have value $null, which is converted to int 0
Quando viene richiamato uno script, una funzione, un filtro o un cmdlet, un argomento può essere associato al parametro corrispondente in base al nome. Questa operazione viene eseguita usando un parametro con argomento , ovvero un argomento che corrisponde al nome del parametro con un trattino iniziale (-), seguito dal valore associato per tale argomento. Il nome del parametro usato può avere qualsiasi ortografia senza distinzione tra maiuscole e minuscole e può usare qualsiasi prefisso che designi in modo univoco il parametro corrispondente. Quando si scelgono i nomi dei parametri, evitare di usare i nomi dei parametri comuni.
Si considerino le chiamate seguenti alla funzione Get-Power:
Get-Power -Base 5 -Exponent 3 # -Base designates $Base, so 5 is
# bound to that, -Exponent designates
# $Exponent, so 3 is bound to that
Get-Power -Exp 3 -Bas 5 # $Base takes on 5 and $Exponent takes on 3
Get-Power -E 3 -B 5 # $Base takes on 5 and $Exponent takes on 3
D'altra parte, chiama alla funzione seguente
function Get-Hypot ([double]$Side1, [double]$Side2) {
return [Math]::Sqrt($Side1 * $Side1 + $Side2 * $Side2)
}
deve usare parametri -Side1 e -Side2, perché non esiste alcun prefisso che designa in modo univoco il parametro .
Lo stesso nome di parametro non può essere usato più volte con o senza valori di argomento associati diversi.
I parametri possono avere attributi (§12). Per informazioni sui singoli attributi, vedere le sezioni all'interno di §12.3. Per informazioni sui set di parametri, vedere §12.3.7.
Uno script, una funzione, un filtro o un cmdlet può ricevere argomenti tramite la riga di comando di chiamata, dalla pipeline o da entrambi. Ecco i passaggi, in ordine, per la risoluzione dell'associazione di parametri:
- Associare tutti i parametri nominati, quindi
- Associare i parametri posizionali, quindi
- Associare dalla pipeline per valore (§12.3.7) con corrispondenza esatta, quindi
- Eseguire il binding dalla pipeline per valore (§12.3.7) con conversione, quindi
- Associare dalla pipeline in base al nome (§12.3.7) con corrispondenza esatta, quindi
- Eseguire l'associazione dalla pipeline per nome (§12.3.7) con conversione
Diversi di questi passaggi comportano la conversione, come descritto in §6. Tuttavia, il set di conversioni usate nell'associazione non corrisponde esattamente a quello usato nelle conversioni di linguaggio. Specificamente
- Anche se è possibile eseguire il cast del valore
$nulla bool,$nullnon può essere associato abool. - Quando il valore
$nullviene passato a un parametro switch per un cmdlet, viene considerato come se$truefosse stato passato. Tuttavia, quando viene passato a un parametro switch per una funzione, viene considerato come se$falsefosse stato passato. - I parametri di tipo bool o switch possono essere associati solo a argomenti numerici o bool.
- Se il tipo di parametro non è una raccolta, ma l'argomento è una sorta di raccolta, non viene tentata alcuna conversione a meno che il tipo di parametro non sia oggetto o PsObject. Il punto principale di questa restrizione consiste nel impedire la conversione di una raccolta in un parametro stringa. In caso contrario, vengono tentate le normali conversioni.
Se il tipo di parametro è IList o ICollection<T>, vengono tentate solo le conversioni tramite Costruttore, op_Implicit e op_Explicit. Se tali conversioni non esistono, viene usata una conversione speciale per i parametri di tipo "collection", che include IListICollection<T>, e matrici.
Se possibile, i parametri posizionali preferiscono essere associati senza conversione dei tipi. Ad esempio:
function Test {
[CmdletBinding(DefaultParameterSetName = "SetB")]
param([Parameter(Position = 0, ParameterSetName = "SetA")]
[decimal]$Dec,
[Parameter(Position = 0, ParameterSetName = "SetB")]
[int]$In
)
$PSCmdlet.ParameterSetName
}
Test 42d # outputs "SetA"
Test 42 # outputs "SetB"