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 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.2 obsahuje experimentální funkci PSNativeCommandArgumentPassing , která mění způsob analýzy příkazového řádku pro nativní příkazy. Další informace najdete v tématu Použití experimentálních funkcí.

Upozornění

Nové chování je zásadní změnou chování prostředí Windows PowerShell 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>

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 parametr New-Item Name 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é