Condividi tramite


informazioni_su_Parsing

Breve descrizione

Descrive il modo in cui PowerShell analizza i comandi.

Descrizione lunga

Quando si immette un comando al prompt dei comandi, PowerShell suddivide il testo del comando in una serie di segmenti denominati token e quindi determina come interpretare ogni token.

Ad esempio, se si digita:

Write-Host book

PowerShell suddivide il comando in due token, Write-Host e booke interpreta ogni token in modo indipendente usando una delle due modalità di analisi principali: modalità di espressione e modalità argomento.

Nota

Quando PowerShell analizza l'input del comando tenta di risolvere i nomi dei comandi in cmdlet o eseguibili nativi. Se un nome di comando non ha una corrispondenza esatta, PowerShell antepone Get- al comando come verbo predefinito. PowerShell, ad esempio, analizza Service come Get-Service. Non è consigliabile usare questa funzionalità per i motivi seguenti:

  • È inefficiente. In questo modo PowerShell esegue la ricerca più volte.
  • I programmi esterni con lo stesso nome vengono risolti per primi, quindi non è possibile eseguire il cmdlet previsto.
  • Get-Help e Get-Command non riconoscono nomi senza verbo.
  • Il nome del comando può essere una parola riservata o una parola chiave del linguaggio. Process è entrambi e non può essere risolto in Get-Process.

Modalità di espressione

La modalità di espressione è destinata alla combinazione di espressioni, necessarie per la manipolazione dei valori in un linguaggio di scripting. Le espressioni sono rappresentazioni di valori nella sintassi di PowerShell e possono essere semplici o composite, ad esempio:

Le espressioni letterali sono rappresentazioni dirette dei relativi valori:

'hello'
32

Le espressioni di variabile contengono il valore della variabile a cui fanno riferimento:

$x
$Script:path

Gli operatori combinano altre espressioni per la valutazione:

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • valori letterali stringa carattere devono essere contenuti tra virgolette.
  • Numeri vengono considerati come valori numerici anziché come una serie di caratteri (a meno che non siano esclusi con un carattere di escape).
  • operatori , inclusi operatori unari come - e -not e operatori binari come + e -gt, vengono interpretati come operatori e applicano le rispettive operazioni sui relativi argomenti (operandi).
  • le espressioni di conversione e attributo vengono analizzate come espressioni e applicate alle espressioni subordinate. Ad esempio: [int] '7'.
  • I riferimenti delle variabili vengono valutati ai relativi valori, ma lo splatting è vietato e genera un errore del parser.
  • Qualsiasi altro elemento viene considerato come un comando da richiamare.

Modalità argomento

Durante l'analisi, PowerShell cerca prima di tutto di interpretare l'input come espressione. Tuttavia, quando viene rilevata una chiamata al comando, l'analisi continua in modalità argomento. Se si dispone di argomenti che contengono spazi, ad esempio percorsi, è necessario racchiudere tali valori di argomento tra virgolette.

La modalità argomento è progettata per l'analisi di argomenti e parametri per i comandi in un ambiente shell. Tutto l'input viene considerato come una stringa espandibile a meno che non usi una delle sintassi seguenti:

  • Segno di dollaro ($) seguito da un nome di variabile inizia un riferimento a variabile, altrimenti viene interpretato come parte della stringa espandibile. Il riferimento alla variabile può includere l'accesso ai membri o l'indicizzazione.

    • I caratteri aggiuntivi che seguono riferimenti a variabili semplici, ad esempio $HOME, vengono considerati parte dello stesso argomento. Racchiudere il nome della variabile tra parentesi graffe ({}) per separarlo dai caratteri successivi. Ad esempio, ${HOME}.
    • Quando il riferimento alla variabile include l'accesso ai membri, il primo carattere tra quelli aggiuntivi viene considerato l'inizio di un nuovo argomento. Ad esempio, $HOME.Length-more restituisce due argomenti: il valore di $HOME.Length e la stringa letterale -more.
  • Virgolette (' e ") indicano l'inizio delle stringhe

  • Parentesi graffe ({}) iniziano un nuovo blocco di script

  • Le virgole (,) introducono elenchi passati come matrici, a meno che il comando chiamato non sia un'applicazione nativa, nel qual caso vengono interpretati come parte della stringa espandibile. Le virgole iniziali, consecutive o finali non sono supportate.

  • Parentesi (()) iniziano una nuova espressione

  • L'operatore Subexpression ($()) inizia un'espressione incorporata

  • Initial at sign (@) inizia le sintassi delle espressioni, ad esempio splatting (@args), matrici (@(1,2,3)) e valori letterali della tabella hash (@{a=1;b=2}).

  • (), $()e @() all'inizio di un token creare un nuovo contesto di analisi che può contenere espressioni o comandi annidati.

    • Se seguito da caratteri aggiuntivi, il primo carattere aggiuntivo viene considerato l'inizio di un nuovo argomento separato.
    • Se preceduto da un valore letterale senza virgolette, $() funziona come una stringa espandibile, () avvia un nuovo argomento che è un'espressione, e @() viene considerato un letterale @, con () che avvia un nuovo argomento che è un'espressione.
  • Tutto il resto viene considerato come una stringa espandibile, ad eccezione dei metacharacter che richiedono ancora l'escape. Consultare Gestione dei caratteri speciali.

    • I metacaratteri in modalità argomento (caratteri con un significato sintattico speciale) sono: <space> ' " ` , ; ( ) { } | & < > @ #. Di questi, < > @ # sono speciali solo all'inizio di un token.
  • Il token di interruzione dell'analisi (--%) altera l'interpretazione di tutti gli argomenti rimanenti. Per altre informazioni, vedere la sezione token di arresto dell'analisi qui sotto.

Esempi

La tabella seguente fornisce diversi esempi di token elaborati in modalità di espressione e modalità di argomento e la valutazione di tali token. Per questi esempi, il valore della variabile $a è 4.

Esempio Modalità Risultato
2 Espressione 2 (intero)
`2 Espressione "2" (comando)
Write-Output 2 Espressione 2 (intero)
2+2 Espressione 4 (intero)
Write-Output 2+2 Argomento "2+2" (una stringa)
Write-Output(2+2) Espressione 4 (intero)
$a Espressione 4 (intero)
Write-Output $a Espressione 4 (intero)
$a+2 Espressione 6 (intero)
Write-Output $a+2 Argomento "4+2" (stringa)
$- Argomento "$-" (comando)
Write-Output $- Argomento "$-" (string)
a$a Espressione a$a (comando)
Write-Output a$a Argomento "a4" (stringa)
a'$a' Espressione a$a (comando)
Write-Output a'$a' Argomento "a$a" (stringa)
a"$a" Espressione a$a (comando)
Write-Output a"$a" Argomento "a4" (stringa)
a$(2) Espressione "a$(2)" (comando)
Write-Output a$(2) Argomento a2 (stringa)

Ogni token può essere interpretato come un tipo di oggetto, ad esempio Boolean o String. PowerShell tenta di determinare il tipo di oggetto dall'espressione. Il tipo di oggetto dipende dal tipo di parametro previsto da un comando e dal fatto che PowerShell sappia convertire l'argomento nel tipo corretto. Nella tabella seguente vengono illustrati diversi esempi dei tipi assegnati ai valori restituiti dalle espressioni.

Esempio Modalità Risultato
Write-Output !1 discussione "!1" (stringa)
Write-Output (!1) espressione Falso (Booleano)
Write-Output (2) espressione 2 (intero)
Set-Variable AB A,B discussione 'A','B' (matrice)
CMD /CECHO A,B discussione 'A,B' (stringa)
CMD /CECHO $AB espressione 'A B' (matrice)
CMD /CECHO :$AB discussione ':A B' (stringa)

Gestione di caratteri speciali

Il carattere di backtick (`) può essere usato per sfuggire qualsiasi carattere speciale in un'espressione. Questo è più utile per l'escapare dei metacaratteri in modalità d'argomento da usare come caratteri letterali anziché come metacaratteri. Ad esempio, per usare il segno di dollaro ($) come valore letterale in una stringa espandibile:

"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.

Continuazione riga

Il carattere backtick può essere usato anche alla fine di una riga per consentire di continuare l'input nella riga successiva. Ciò consente di migliorare la leggibilità di un comando che accetta diversi parametri con nomi lunghi e valori di argomento. Per esempio:

New-AzVm `
    -ResourceGroupName "myResourceGroupVM" `
    -Name "myVM" `
    -Location "EastUS" `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -Credential $cred

Tuttavia, dovresti evitare di usare la continuazione di riga.

  • I personaggi di backtick possono essere difficili da vedere e facile da dimenticare.
  • Uno spazio aggiuntivo dopo il backtick interrompe la continuità della riga. Poiché lo spazio è difficile da vedere, può essere difficile trovare l'errore.

PowerShell offre diversi modi per suddividere le linee in punti naturali nella sintassi.

  • Dopo i caratteri pipe (|)
  • Dopo gli operatori binari (+, -, -eqe così via)
  • Dopo le virgole (,) in una matrice
  • Dopo l'apertura di caratteri come [, {, (

Per un insieme di parametri di grandi dimensioni, utilizza invece lo splatting. Per esempio:

$parameters = @{
    ResourceGroupName = "myResourceGroupVM"
    Name = "myVM"
    Location = "EastUS"
    VirtualNetworkName = "myVnet"
    SubnetName = "mySubnet"
    SecurityGroupName = "myNetworkSecurityGroup"
    PublicIpAddressName = "myPublicIpAddress"
    Credential = $cred
}
New-AzVm @parameters

Passaggio di argomenti a comandi nativi

Quando si eseguono comandi nativi da PowerShell, gli argomenti vengono prima analizzati da PowerShell. Gli argomenti analizzati vengono quindi uniti in una singola stringa con ogni parametro separato da uno spazio.

Ad esempio, il comando seguente chiama il programma icacls.exe.

icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

Per eseguire questo comando in PowerShell 2.0, è necessario usare caratteri di escape per impedire a PowerShell di interpretazione errata delle parentesi.

icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F

Token di interruzione dell'analisi

A partire da PowerShell 3.0, è possibile usare il token di arresto dell'analisi (--%) per impedire a PowerShell di interpretare l'input come comandi o espressioni di PowerShell.

Nota

Il token di arresto dell'analisi è destinato solo all'uso di comandi nativi nelle piattaforme Windows.

Quando si chiama un comando nativo, mettere il token di interruzione dell'analisi prima degli argomenti del programma. Questa tecnica è molto più semplice rispetto all'uso di caratteri di escape per evitare errori di interpretazione.

Quando incontra un token che interrompe l'analisi, PowerShell tratta i caratteri rimanenti nella riga come testo letterale. L'unica interpretazione eseguita consiste nel sostituire i valori per le variabili di ambiente che usano la notazione standard di Windows, ad esempio %USERPROFILE%.

icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F

PowerShell invia la stringa di comando seguente al programma icacls.exe:

X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

Il token di "protezione dell'analisi" è valido solo fino al successivo carattere di nuova riga o di pipeline. Non è possibile usare il carattere di continuazione della riga (`) per estenderne l'effetto o usare un delimitatore di comando (;) per terminarne l'effetto.

Oltre a %variable% riferimenti a variabili di ambiente, non è possibile incorporare altri elementi dinamici nel comando. L'escape di un carattere % in %%, come si può fare nei file batch, non è supportato. %<name>% i token vengono espansi invariabilmente. Se <name> non fa riferimento a una variabile di ambiente definita, il token viene passato attraverso as-is.

Non è possibile usare il reindirizzamento del flusso (ad esempio >file.txt) perché vengono passati così come sono come argomenti al comando di destinazione.

Nell'esempio seguente, il primo passaggio esegue un comando senza usare il token di stop parsing. PowerShell valuta la stringa tra virgolette e passa il valore (senza virgolette) a cmd.exe, che genera un errore.

PS> cmd /c echo "a|b"
'b' is not recognized as an internal or external command,
operable program or batch file.
PS> cmd /c --% echo "a|b"
"a|b"

Nota

Il token di arresto dell'analisi non è necessario quando si usano i cmdlet di PowerShell. Tuttavia, può essere utile passare argomenti a una funzione di PowerShell progettata per chiamare un comando nativo con tali argomenti.

Passaggio di argomenti contenenti caratteri virgolette

Alcuni comandi nativi prevedono argomenti che contengono caratteri virgolette. PowerShell 7.3 ha modificato la modalità di analisi della riga di comando per i comandi nativi.

Cautela

Il nuovo comportamento è una modifica interruttiva rispetto al comportamento di Windows PowerShell 5.1. Questo può interrompere gli script e l'automazione che possono risolvere i vari problemi quando si richiamano applicazioni native. Usare il token di interruzione dell'analisi (--%) o il cmdlet Start-Process per evitare il passaggio dell'argomento nativo quando necessario.

La nuova variabile di preferenza $PSNativeCommandArgumentPassing controlla questo comportamento. Questa variabile consente di selezionare il comportamento in fase di esecuzione. I valori validi sono Legacy, Standarde Windows. Il comportamento predefinito è specifico della piattaforma. Nelle piattaforme Windows, l'impostazione predefinita è Windows e le piattaforme non Windows hanno come impostazione predefinita Standard.

Legacy è il comportamento storico. Il comportamento delle modalità Windows e Standard è identico, eccetto che, in modalità Windows, le chiamate ai file seguenti usano automaticamente il passaggio degli argomenti in stile Legacy.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • terminando con .bat
  • terminando con .cmd
  • terminando con .js
  • terminando con .vbs
  • terminando con .wsf

Se il $PSNativeCommandArgumentPassing è impostato su Legacy o Standard, il parser non verifica la presenza di questi file.

Nota

Gli esempi seguenti usano lo strumento TestExe.exe. È possibile compilare TestExe dal codice sorgente. Consulta TestExe nel repository sorgente di PowerShell.

Nuovi comportamenti resi disponibili da questa modifica:

  • Le stringhe letterali o espandibili con virgolette incorporate vengono ora mantenute:

    PS> $a = 'a" "b'
    PS> TestExe -echoargs $a 'c" "d' e" "f
    Arg 0 is <a" "b>
    Arg 1 is <c" "d>
    Arg 2 is <e f>
    
  • Le stringhe vuote come argomenti vengono ora mantenute:

    PS> TestExe -echoargs '' a b ''
    Arg 0 is <>
    Arg 1 is <a>
    Arg 2 is <b>
    Arg 3 is <>
    

L'obiettivo di questi esempi è passare il percorso della directory (con spazi e virgolette) "C:\Program Files (x86)\Microsoft\" a un comando nativo in modo che abbia ricevuto il percorso come stringa tra virgolette.

In modalità Windows o Standard, gli esempi seguenti producono i risultati previsti:

TestExe -echoargs """${Env:ProgramFiles(x86)}\Microsoft\"""
TestExe -echoargs '"C:\Program Files (x86)\Microsoft\"'

Per ottenere gli stessi risultati in modalità Legacy, è necessario annullare l'effetto delle virgolette o usare il token di arresto dell'analisi (--%):

TestExe -echoargs """""${Env:ProgramFiles(x86)}\Microsoft\\"""""
TestExe -echoargs "\""C:\Program Files (x86)\Microsoft\\"""
TestExe -echoargs --% ""\""C:\Program Files (x86)\Microsoft\\"\"""
TestExe -echoargs --% """C:\Program Files (x86)\Microsoft\\""
TestExe -echoargs --% """%ProgramFiles(x86)%\Microsoft\\""

Nota

Il carattere barra rovesciata (\) non viene riconosciuto come carattere di escape da PowerShell. È il carattere di escape usato dall'API sottostante per ProcessStartInfo.ArgumentList.

PowerShell 7.3 ha anche aggiunto la possibilità di tracciare l'associazione dei parametri per i comandi nativi. Per altre informazioni, vedere trace-command.

Passaggio di argomenti ai comandi di PowerShell

A partire da PowerShell 3.0, è possibile utilizzare il token end-of-parameters (--) per impedire a PowerShell di interpretare l'input come parametri di PowerShell. Si tratta di una convenzione specificata nella specifica POSIX Shell e Utilities.

Token di fine parametri

Il token di fine parametri (--) indica che tutti gli argomenti seguenti devono essere passati nella loro forma originale come se le virgolette doppie fossero poste intorno a loro. Ad esempio, usando -- è possibile restituire la stringa -InputObject senza usare virgolette o averla interpretata come parametro:

Write-Output -- -InputObject
-InputObject

A differenza del token di arresto dell'analisi (--%), tutti i valori che seguono il token -- possono essere interpretati come espressioni da PowerShell.

Write-Output -- -InputObject $Env:PROCESSOR_ARCHITECTURE
-InputObject
AMD64

Questo comportamento si applica solo ai comandi di PowerShell. Se si usa il token -- quando si chiama un comando esterno, la stringa -- viene passata come argomento a tale comando.

TestExe -echoargs -a -b -- -c

L'output mostra che -- viene passato come argomento a TestExe.

Arg 0 is <-a>
Arg 1 is <-b>
Arg 2 is <-->
Arg 3 is <-c>

Tilde (~)

Il carattere tilde (~) ha un significato speciale in PowerShell. Quando viene usato con i comandi di PowerShell all'inizio di un percorso, PowerShell espande il carattere tilde nella home directory dell'utente. Se si usa il carattere tilde ovunque in un percorso, viene considerato come un carattere letterale.

PS D:\temp> $PWD

Path
----
D:\temp

PS D:\temp> Set-Location ~
PS C:\Users\user2> $PWD

Path
----
C:\Users\user2

In questo esempio, il parametro Name del New-Item prevede una stringa. Il carattere tilde viene trattato come carattere letterale. Per accedere alla directory appena creata, è necessario specificare il percorso con il carattere tilde.

PS D:\temp> Set-Location ~
PS C:\Users\user2> New-Item -Type Directory -Name ~

    Directory: C:\Users\user2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----            5/6/2024  2:08 PM                ~

PS C:\Users\user2> Set-Location ~
PS C:\Users\user2> Set-Location .\~
PS C:\Users\user2\~> $PWD

Path
----
C:\Users\user2\~

PowerShell 7.5-preview.2 aggiunge una funzionalità sperimentale per espandere il simbolo tilde alla directory home dell'utente per i comandi nativi. Per ulteriori informazioni, vedere la funzionalità PSNativeWindowsTildeExpansion in Utilizzo delle funzionalità sperimentali in PowerShell.

La stringa espansa viene passata al comando nativo. Espandendo la tilde, PowerShell evita errori per i comandi nativi di Windows che non supportano il carattere tilde. È possibile visualizzare la stringa risultante tracciando l'associazione di parametri usando Trace-Command.

Trace-Command -Name ParameterBinding -Expression {
    findstr /C:\foo" ~\repocache.clixml
} -PSHost
DEBUG: 2024-05-06 15:13:46.8268 ParameterBinding Information: 0 : BIND NAMED native application line args [C:\Windows\system32\findstr.exe]
DEBUG: 2024-05-06 15:13:46.8270 ParameterBinding Information: 0 :     BIND cmd line arg [/C:\oo] to position [0]
DEBUG: 2024-05-06 15:13:46.8271 ParameterBinding Information: 0 :     BIND cmd line arg [C:\Users\user2\repocache.clixml] to position [1]
DEBUG: 2024-05-06 15:13:46.8322 ParameterBinding Information: 0 : CALLING BeginProcessing

Si noti che ~\repocache.clixml è stato espanso in C:\Users\user2\repocache.clixml.

Vedere anche