about_Parsing

Krátký popis

Popisuje, jak PowerShell analyzuje příkazy.

Dlouhý popis

Když zadáte příkaz na příkazovém řádku, PowerShell rozdělí text příkazu do řady segmentů, které se nazývají tokeny, a pak určí, jak interpretovat jednotlivé tokeny .

Pokud například zadáte:

Write-Host book

PowerShell rozdělí příkaz na dva tokeny a bookinterpretuje každý token nezávisle pomocí jednoho ze dvou hlavních režimů analýzy: režim výrazu Write-Host a režim argumentu.

Poznámka:

Když PowerShell analyzuje vstup příkazu, pokusí se přeložit názvy příkazů na rutiny nebo nativní spustitelné soubory. Pokud název příkazu nemá přesnou shodu, PowerShell se k příkazu předpovědí Get- jako výchozí příkaz. PowerShell například parsuje Service jako Get-Service. Tuto funkci nedoporučujeme používat z následujících důvodů:

  • Je neefektivní. To způsobí, že PowerShell bude prohledávat vícekrát.
  • Externí programy se stejným názvem se nejprve přeloží, takže zamýšlenou rutinu nemusíte spustit.
  • Get-Help a Get-Command nerozpoznávejte názvy bez sloves.
  • Název příkazu může být vyhrazené slovo nebo klíčové slovo jazyka. Process je obojí a nelze je vyřešit na Get-Process.

Režim výrazu

Režim výrazů je určený ke kombinování výrazů, které jsou vyžadovány pro manipulaci s hodnotami ve skriptovacím jazyce. Výrazy představují reprezentaci hodnot v syntaxi PowerShellu a můžou být jednoduché nebo složené, například:

Literální výrazy představují přímé vyjádření jejich hodnot:

'hello'
32

Výrazy proměnných mají hodnotu proměnné, na kterou odkazují:

$x
$script:path

Operátory kombinují další výrazy pro vyhodnocení:

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • Řetězcové literály znaků musí být obsaženy v uvozovkách.
  • Čísla se považují za číselné hodnoty, nikoli jako řadu znaků (pokud nejsou uchycené).
  • Operátory, včetně unárních operátorů, jako - jsou a -not binární operátory + jako a -gt, jsou interpretovány jako operátory a aplikují jejich příslušné operace na argumenty (operandy).
  • Výrazy atributů a převodu se analyzují jako výrazy a použijí se u podřízených výrazů. Například: [int] '7'.
  • Odkazy na proměnné se vyhodnocují na jejich hodnoty, ale splatting je zakázáno a způsobí chybu analyzátoru.
  • Cokoli jiného se považuje za příkaz, který se má vyvolat.

Režim argumentu

Při analýze powershell nejprve interpretuje vstup jako výraz. Při vyvolání příkazu ale probíhá analýza v režimu argumentu. Pokud máte argumenty, které obsahují mezery, například cesty, musíte tyto hodnoty argumentů uzavřít do uvozovek.

Režim argumentů je určený pro analýzu argumentů a parametrů pro příkazy v prostředí prostředí. Veškerý vstup se považuje za rozbalitelný řetězec, pokud nepoužívá jednu z následujících syntaxí:

  • Znak dolaru ($) následovaný názvem proměnné začíná odkaz na proměnnou, jinak se interpretuje jako součást rozbalitelného řetězce. Odkaz na proměnnou může zahrnovat přístup ke členům nebo indexování.

    • Další znaky, které následují po jednoduchých odkazech na proměnné, jako $HOMEnapříklad , jsou považovány za součást stejného argumentu. Uzavřete název proměnné do složených závorek () a{} oddělte ho od dalších znaků. Například ${HOME}.
    • Pokud odkaz na proměnnou obsahuje přístup člena, první z dalších znaků se považuje za začátek nového argumentu. Výsledkem jsou například $HOME.Length-more dva argumenty: hodnota řetězcového $HOME.Length literálu -more.
  • Uvozovky (' a ") počáteční řetězce

  • Složené závorky ({}) začínají novým blokem skriptu.

  • Čárky (,) představují seznamy předané jako pole, pokud není volaný příkaz nativní aplikací, v takovém případě jsou interpretovány jako součást rozbalitelného řetězce. Počáteční, po sobě jdoucí nebo koncové čárky se nepodporují.

  • Závorky (()) začínají novým výrazem

  • Operátor dílčího výrazu ($()) začíná vložený výraz.

  • Počáteční znak (@) začíná syntaxe výrazů, jako jsou splatting (@args), matice (@(1,2,3)) a literály hashovací tabulky (@{a=1;b=2}).

  • ()@() a $()na začátku tokenu vytvořte nový kontext analýzy, který může obsahovat výrazy nebo vnořené příkazy.

    • Když následuje další znaky, první další znak se považuje za začátek nového samostatného argumentu.
    • Když předchází necitovaný literál $() , funguje jako rozbalitelný řetězec, () spustí nový argument, který je výrazem, a @() použije se jako literál @ při () spuštění nového argumentu, který je výrazem.
  • Všechno ostatní je považováno za rozbalitelný řetězec, s výjimkou metacharacterů, které stále potřebují utéct. Viz Zpracování speciálních znaků.

    • Metacharaktery v režimu argumentu (znaky se speciálním syntaktickým významem) jsou: <space> ' " ` , ; ( ) { } | & < > @ #. Z nich < > @ # jsou pouze speciální na začátku tokenu.
  • Token zastavení parsování (--%) změní interpretaci všech zbývajících argumentů. Další informace najdete v části zastavení analýzy tokenu níže.

Příklady

Následující tabulka obsahuje několik příkladů tokenů zpracovaných v režimu výrazů a v režimu argumentů a vyhodnocení těchto tokenů. V těchto příkladech je 4hodnota proměnné $a .

Příklad Režim Výsledek
2 Výraz 2 (celé číslo)
`2 Výraz "2" (příkaz)
Write-Output 2 Výraz 2 (celé číslo)
2+2 Výraz 4 (celé číslo)
Write-Output 2+2 Argument "2+2" (řetězec)
Write-Output(2+2) Výraz 4 (celé číslo)
$a Výraz 4 (celé číslo)
Write-Output $a Výraz 4 (celé číslo)
$a+2 Výraz 6 (celé číslo)
Write-Output $a+2 Argument "4+2" (řetězec)
$- Argument "$-" (příkaz)
Write-Output $- Argument "$-" (řetězec)
a$a Výraz "a$a" (příkaz)
Write-Output a$a Argument "a4" (řetězec)
a'$a' Výraz "a$a" (příkaz)
Write-Output a'$a' Argument "a$a" (řetězec)
a"$a" Výraz "a$a" (příkaz)
Write-Output a"$a" Argument "a4" (řetězec)
a$(2) Výraz "a$(2)" (příkaz)
Write-Output a$(2) Argument "a2" (řetězec)

Každý token lze interpretovat jako určitý druh typu objektu, například logická hodnota nebo řetězec. PowerShell se pokusí určit typ objektu z výrazu. Typ objektu závisí na typu parametru, který příkaz očekává, a na tom, jestli PowerShell ví, jak převést argument na správný typ. Následující tabulka uvádí několik příkladů typů přiřazených hodnotám vráceným výrazy.

Příklad Režim Výsledek
Write-Output !1 Argument "!1" (řetězec)
Write-Output (!1) výraz False (logická hodnota)
Write-Output (2) výraz 2 (celé číslo)
Set-Variable AB A,B Argument "A", "B" (pole)
CMD /CECHO A,B Argument "A,B" (řetězec)
CMD /CECHO $AB výraz A B (matice)
CMD /CECHO :$AB Argument ':A B' (řetězec)

Zpracování speciálních znaků

Zpětný znak (`) lze použít k řídicímu znaku libovolného speciálního znaku ve výrazu. To je nejužitečnější pro odstranění metacharakterů v režimu argumentů, které chcete použít jako literální znaky, nikoli jako metacharakter. Pokud chcete například použít znak dolaru ($) jako literál v rozbalitelném řetězci:

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

Pokračování řádku

Znak backtick lze také použít na konci řádku, abyste mohli pokračovat ve vstupu na dalším řádku. To zlepšuje čitelnost příkazu, který trvá několik parametrů s dlouhými názvy a hodnotami argumentů. Příklad:

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

Měli byste se však vyhnout použití pokračování řádku.

  • Zpětné znaky mohou být obtížně vidět a snadno zapomenout.
  • Nadbytečné mezery po zpětném návazci přeruší pokračování řádku. Vzhledem k tomu, že je místo obtížně vidět, může být obtížné najít chybu.

PowerShell nabízí několik způsobů, jak zalomit čáry v přirozeném bodě syntaxe.

  • Za znaky svislé znaky (|)
  • Za binárními operátory (+, -, -eqatd.)
  • Za čárkou (,) v poli
  • Po otevření znaků, například [, {(

Pro velkou sadu parametrů použijte místo toho splatting. Příklad:

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

Předávání argumentů nativním příkazům

Při spouštění nativních příkazů z PowerShellu se argumenty nejprve parsují pomocí PowerShellu. Analyzované argumenty se pak spojí do jednoho řetězce s každým parametrem odděleným mezerou.

Například následující příkaz volá icacls.exe program.

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

Pokud chcete tento příkaz spustit v PowerShellu 2.0, musíte použít řídicí znaky, abyste zabránili chybné interpretaci závorek v PowerShellu.

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

Token zastavení analýzy

Počínaje PowerShellem 3.0 můžete pomocí tokenu stop-parsing (--%) zastavit interpretovat vstup jako powershellové příkazy nebo výrazy.

Poznámka:

Token stop-parsing je určen pouze pro použití nativních příkazů na platformách Windows.

Při volání nativního příkazu před argumenty programu umístěte token stop-parsing. Tato technika je mnohem jednodušší než použití řídicích znaků, aby se zabránilo nesprávné interpretaci.

Když dojde k zastavení parsování tokenu, PowerShell považuje zbývající znaky na řádku za literál. Jedinou interpretací, kterou provádí, je nahradit hodnoty proměnných prostředí, které používají standardní notaci systému Windows, například %USERPROFILE%.

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

PowerShell odešle do icacls.exe programu následující příkazový řetězec:

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

Token zastavení parsování je efektivní jenom do dalšího znaku nového řádku nebo kanálu. Znak pokračování řádku (`) nelze použít k rozšíření jeho efektu nebo k ukončení jeho efektu použijte oddělovač příkazů (;).

%variable% Kromě odkazů na proměnné prostředí nemůžete do příkazu vložit žádné další dynamické prvky. Escaping a % character as %%, the way you can do inside batch files, isn't supported. %<name>% tokeny se neustále rozšiřují. Pokud <name> neodkazuje na definovanou proměnnou prostředí, token se předává tak, jak je.

Přesměrování datového proudu (například >file.txt) nemůžete použít, protože se předávají doslovně jako argumenty cílovému příkazu.

V následujícím příkladu první krok spustí příkaz bez použití tokenu stop-parsing. PowerShell vyhodnotí řetězec v uvozovkách a předá hodnotu (bez uvozovek), což cmd.exezpůsobí chybu.

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"

Poznámka:

Při použití rutin PowerShellu není token stop-parsing potřeba. Může ale být užitečné předat argumenty funkci PowerShellu, která je navržená k volání nativního příkazu s těmito argumenty.

Předávání argumentů obsahujících znaky uvozovek

Některé nativní příkazy očekávají argumenty, které obsahují znaky uvozovek. PowerShell 7.3 změnil způsob analýzy příkazového řádku pro nativní příkazy.

Upozornění

Nové chování je zásadní změna z chování Windows PowerShellu 5.1. To může narušit skripty a automatizaci, které řeší různé problémy při vyvolání nativních aplikací. Pomocí tokenu stop-parsing (--%) nebo Start-Process rutiny se v případě potřeby vyhněte předávání nativních argumentů.

Toto chování řídí nová $PSNativeCommandArgumentPassing proměnná předvoleb. Tato proměnná umožňuje vybrat chování za běhu. Platné hodnoty jsou Legacy, Standarda Windows. Výchozí chování je specifické pro platformu. Na platformách Windows je Windows výchozí nastavení a jiné platformy než Windows .Standard

Legacy je historické chování. Chování Windows a Standard režim jsou stejné s výjimkou Windows vyvolání následujících souborů v režimu automaticky používají Legacy předávání argumentu stylu.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • končící na .bat
  • končící na .cmd
  • končící na .js
  • končící na .vbs
  • končící na .wsf

Pokud je tato možnost $PSNativeCommandArgumentPassing nastavená na hodnotu Legacy nebo Standard, analyzátor tyto soubory nekontroluje.

Poznámka:

Následující příklady používají TestExe.exe nástroj. Můžete sestavovat TestExe ze zdrojového kódu. Viz TestExe ve zdrojovém úložišti PowerShellu.

Nové chování zpřístupněné touto změnou:

  • Literály nebo rozbalitelné řetězce s vloženými uvozovkami jsou nyní zachovány:

    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>
    
  • Prázdné řetězce jako argumenty se teď zachovají:

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

Cílem těchto příkladů je předat cestu k adresáři (s mezerami a uvozovkami) "C:\Program Files (x86)\Microsoft\" nativnímu příkazu, aby získal cestu jako řetězec v uvozovkách.

Následující příklady v Windows nebo Standard režimu vytvářejí očekávané výsledky:

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

Pokud chcete získat stejné výsledky v Legacy režimu, musíte uvozovky uvozovky nebo použít token zastavení parsování (--%):

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\\""

Poznámka:

Zpětný lomítko (\) není v PowerShellu rozpoznán jako řídicí znak. Jedná se o řídicí znak používaný podkladovým rozhraním API pro ProcessStartInfo.ArgumentList.

PowerShell 7.3 také přidal možnost trasovat vazbu parametrů pro nativní příkazy. Další informace naleznete v tématu Trace-Command.

Předávání argumentů příkazům PowerShellu

Počínaje PowerShellem 3.0 můžete pomocí tokenu koncového parametru (--) zastavit interpretaci vstupu jako parametrů PowerShellu. Toto je konvence zadaná ve specifikaci prostředí POSIX a nástrojů.

Token koncového parametru

Token konce parametrů (--) označuje, že všechny argumenty, které následují, mají být předány ve skutečné podobě, jako by se kolem nich umístily dvojité uvozovky. Když například použijete -- výstup řetězce -InputObject bez použití uvozovek nebo ho interpretujete jako parametr:

Write-Output -- -InputObject
-InputObject

Na rozdíl od tokenu stop-parsing (--%) je možné všechny hodnoty následující za -- tokenem interpretovat jako výrazy pomocí PowerShellu.

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

Toto chování platí jenom pro příkazy PowerShellu. Pokud token použijete -- při volání externího příkazu, -- řetězec se předá jako argument pro tento příkaz.

TestExe -echoargs -a -b -- -c

Výstup ukazuje, že -- se předává jako argument .TestExe

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

Viz také