Sdílet prostřednictvím


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 Write-Hostinterpretuje každý token nezávisle pomocí jednoho ze dvou hlavních režimů analýzy: režim výrazu book 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 $ahodnota proměnné 4 .

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. Za normálních okolností analýza příkazového řádku PowerShellu odebere zadaný znak uvozovky. Analyzované argumenty se pak spojí do jednoho řetězce s každým parametrem odděleným mezerou. Tento řetězec je pak přiřazen k Argument vlastnost objektu ProcessStartInfo . Uvozovky v řetězci musí být uvozovky uvozovky nebo zpětné lomítko (\) znaky.

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.Arguments.

Další informace o požadavcích na řídicí příkaz naleznete v dokumentaci pro ProcessStartInfo.Arguments.

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.

Cílem těchto příkladů je předat cestu "C:\Program Files (x86)\Microsoft\" k adresáři nativnímu příkazu, aby přijala cestu jako řetězec v uvozováku.

Parametr zobrazuje hodnoty přijaté jako argumenty spustitelnému souboru. Tento nástroj můžete použít k ověření, že jste správně uchyceli znaky v argumentech.

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

Výstup je stejný pro všechny příklady:

Arg 0 is <"C:\Program Files (x86)\Microsoft\">

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>

Tilda (~)

Znak tilda (~) má v PowerShellu zvláštní význam. Když se používá s příkazy PowerShellu na začátku cesty, znak tilda se rozbalí do domovského adresáře uživatele. Pokud se znak tilda používá kdekoli jinde v cestě, považuje se za literální znak.

PS D:\temp> $PWD

Path
----
D:\temp

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

Path
----
C:\Users\user2

V tomto příkladu očekává řetězec. Znak tilda se považuje za literální znak. Pokud chcete přejít na nově vytvořený adresář, musíte kvalifikovat cestu znakem tildy.

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

Pokud použijete znak tilda s nativními příkazy, PowerShell předá tilda jako literálový znak. Použití vlnovek v cestě způsobuje chyby nativních příkazů ve Windows, které nepodporují znak tilda.

PS D:\temp> $PWD

Path
----
D:\temp

PS D:\temp> Get-Item ~\repocache.clixml

    Directory: C:\Users\user2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           4/29/2024  3:42 PM          88177 repocache.clixml

PS D:\temp> more.com ~\repocache.clixml
Cannot access file D:\temp\~\repocache.clixml

Viz také