Delen via


about_Parsing

Korte beschrijving

Hierin wordt beschreven hoe PowerShell-opdrachten parseert.

Lange beschrijving

Wanneer u een opdracht invoert bij de opdrachtprompt, breekt PowerShell de opdrachttekst op in een reeks segmenten die tokens worden genoemd en wordt vervolgens bepaald hoe elk token moet worden geïnterpreteerd.

Als u bijvoorbeeld het volgende typt:

Write-Host book

PowerShell breekt de opdracht op in twee tokens, Write-Host en book, en interpreteert elk token onafhankelijk met behulp van een van de twee belangrijkste parseringsmodi: expressiemodus en argumentmodus.

Notitie

Terwijl PowerShell opdrachtinvoer parseert, wordt geprobeerd de opdrachtnamen om te lossen naar cmdlets of systeemeigen uitvoerbare bestanden. Als de naam van een opdracht niet exact overeenkomt, wordt in PowerShell Get- de opdracht als standaardwerkwoord weergegeven. PowerShell parseert Service bijvoorbeeld als Get-Service. Het wordt niet aanbevolen om deze functie te gebruiken om de volgende redenen:

  • Het is inefficiënt. Dit zorgt ervoor dat PowerShell meerdere keren zoekt.
  • Externe programma's met dezelfde naam worden eerst omgezet, dus u kunt de beoogde cmdlet niet uitvoeren.
  • Get-Help en Get-Command worden namen die geen werkwoorden bevatten, niet herkend.
  • De opdrachtnaam kan een gereserveerd woord of een taal trefwoord zijn. Process is beide en kan niet worden omgezet in Get-Process.

Expressiemodus

De expressiemodus is bedoeld voor het combineren van expressies, vereist voor het bewerken van waarden in een scripttaal. Expressies zijn weergaven van waarden in PowerShell-syntaxis en kunnen eenvoudig of samengesteld zijn, bijvoorbeeld:

Letterlijke expressies zijn directe representaties van hun waarden:

'hello'
32

Variabeleexpressies bevatten de waarde van de variabele waarnaar ze verwijzen:

$x
$script:path

Operators combineren andere expressies voor evaluatie:

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • Letterlijke tekenreeksen moeten tussen aanhalingstekens staan.
  • Getallen worden behandeld als numerieke waarden in plaats van als een reeks tekens (tenzij een escape-teken).
  • Operators, inclusief unaire operators zoals - en -not en binaire operators zoals + en -gt, worden geïnterpreteerd als operators en passen hun respectieve bewerkingen toe op hun argumenten (operanden).
  • Kenmerk- en conversieexpressies worden geparseerd als expressies en toegepast op onderliggende expressies. Bijvoorbeeld: [int] '7'.
  • Variabele verwijzingen worden geëvalueerd naar hun waarden, maar splatting is verboden en veroorzaakt een parserfout.
  • Al het andere wordt behandeld als een opdracht die moet worden aangeroepen.

Argumentmodus

Tijdens het parseren wordt in PowerShell eerst gezocht naar het interpreteren van invoer als een expressie. Maar wanneer er een opdrachtaanroep wordt aangetroffen, wordt het parseren voortgezet in de argumentmodus. Als u argumenten hebt die spaties bevatten, zoals paden, moet u deze argumentwaarden tussen aanhalingstekens plaatsen.

De argumentmodus is ontworpen voor het parseren van argumenten en parameters voor opdrachten in een shell-omgeving. Alle invoer wordt behandeld als een uitbreidbare tekenreeks, tenzij een van de volgende syntaxis wordt gebruikt:

  • Het dollarteken ($) gevolgd door de naam van een variabele begint een verwijzing naar een variabele, anders wordt deze geïnterpreteerd als onderdeel van de uitbreidbare tekenreeks. De variabeleverwijzing kan toegang tot leden of indexering omvatten.

    • Aanvullende tekens na eenvoudige variabeleverwijzingen, zoals $HOME, worden beschouwd als onderdeel van hetzelfde argument. Plaats de naam van de variabele tussen accolades ({}) om deze te scheiden van de volgende tekens. Bijvoorbeeld ${HOME}.
    • Wanneer de variabele-verwijzing lidtoegang bevat, wordt de eerste van eventuele extra tekens beschouwd als het begin van een nieuw argument. Resulteert bijvoorbeeld $HOME.Length-more in twee argumenten: de waarde van $HOME.Length en de letterlijke -moretekenreeks .
  • Aanhalingstekens (' en ") beginnen tekenreeksen

  • Accolades ({}) een nieuwe scriptblokken starten

  • Komma's (,) introduceren lijsten die worden doorgegeven als matrices, tenzij de opdracht die wordt aangeroepen een systeemeigen toepassing is, in welk geval ze worden geïnterpreteerd als onderdeel van de uitbreidbare tekenreeks. Begin-, opeenvolgende of afsluitende komma's worden niet ondersteund.

  • Haakjes (()) beginnen met een nieuwe expressie

  • De subexpressieoperator ($()) begint een ingesloten expressie

  • Initial at sign (@) begint expressiesyntaxis, zoals splatting (@args), matrices (@(1,2,3)) en letterlijke hashtabellen (@{a=1;b=2}).

  • (), $()en @() maken aan het begin van een token een nieuwe parseercontext die expressies of geneste opdrachten kan bevatten.

    • Wanneer dit wordt gevolgd door extra tekens, wordt het eerste extra teken beschouwd als het begin van een nieuw, afzonderlijk argument.
    • Wanneer voorafgegaan door een letterlijke waarde $() zonder aanhalingstekens werkt als een uitbreidbare tekenreeks, () wordt een nieuw argument gestart dat een expressie is en @() letterlijk @ wordt genomen bij () het starten van een nieuw argument dat een expressie is.
  • Al het andere wordt behandeld als een uitbreidbare tekenreeks, met uitzondering van metatekens die nog steeds moeten worden ge escaped. Zie Speciale tekens verwerken.

    • De metatekens voor de argumentmodus (tekens met speciale syntactische betekenis) zijn: <space> ' " ` , ; ( ) { } | & < > @ #. < > @ # Deze zijn alleen speciaal aan het begin van een token.
  • Het token voor stoppen parseren (--%) wijzigt de interpretatie van alle resterende argumenten. Zie de sectie stop-parsing token hieronder voor meer informatie.

Voorbeelden

De volgende tabel bevat verschillende voorbeelden van tokens die zijn verwerkt in de expressiemodus en argumentmodus en de evaluatie van deze tokens. Voor deze voorbeelden is 4de waarde van de variabele $a .

Voorbeeld Modus Resultaat
2 Expression 2 (geheel getal)
`2 Expression "2" (opdracht)
Write-Output 2 Expression 2 (geheel getal)
2+2 Expression 4 (geheel getal)
Write-Output 2+2 Argument "2+2" (tekenreeks)
Write-Output(2+2) Expression 4 (geheel getal)
$a Expression 4 (geheel getal)
Write-Output $a Expression 4 (geheel getal)
$a+2 Expression 6 (geheel getal)
Write-Output $a+2 Argument "4+2" (tekenreeks)
$- Argument "$-" (opdracht)
Write-Output $- Argument "$-" (tekenreeks)
a$a Expression "a$a" (opdracht)
Write-Output a$a Argument "a4" (tekenreeks)
a'$a' Expression "a$a" (opdracht)
Write-Output a'$a' Argument "a$a" (tekenreeks)
a"$a" Expression "a$a" (opdracht)
Write-Output a"$a" Argument "a4" (tekenreeks)
a$(2) Expression "a$(2)" (opdracht)
Write-Output a$(2) Argument "a2" (tekenreeks)

Elk token kan worden geïnterpreteerd als een soort objecttype, zoals Booleaanse waarde of tekenreeks. PowerShell probeert het objecttype van de expressie te bepalen. Het objecttype is afhankelijk van het type parameter dat een opdracht verwacht en of PowerShell weet hoe het argument moet worden geconverteerd naar het juiste type. In de volgende tabel ziet u enkele voorbeelden van de typen die zijn toegewezen aan waarden die door de expressies worden geretourneerd.

Voorbeeld Modus Resultaat
Write-Output !1 Argument "!1" (tekenreeks)
Write-Output (!1) expressie Onwaar (Booleaans)
Write-Output (2) expressie 2 (geheel getal)
Set-Variable AB A,B Argument 'A','B' (matrix)
CMD /CECHO A,B Argument 'A,B' (tekenreeks)
CMD /CECHO $AB expressie 'A B' (matrix)
CMD /CECHO :$AB Argument ':A B' (tekenreeks)

Speciale tekens verwerken

Het backtick-teken (`) kan worden gebruikt om een speciaal teken in een expressie te laten ontsnappen. Dit is vooral handig voor het escapen van de metatekens in de argumentmodus die u wilt gebruiken als letterlijke tekens in plaats van als metateken. Als u bijvoorbeeld het dollarteken ($) wilt gebruiken als letterlijke waarde in een uitvouwbare tekenreeks:

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

Regelvervolging

Het backtick-teken kan ook worden gebruikt aan het einde van een regel, zodat u de invoer op de volgende regel kunt voortzetten. Dit verbetert de leesbaarheid van een opdracht die verschillende parameters met lange namen en argumentwaarden gebruikt. Bijvoorbeeld:

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

Vermijd echter het gebruik van regelvervolging.

  • De achtergrondtekens zijn moeilijk te zien en gemakkelijk te vergeten.
  • Een extra spatie nadat de backtick de regelvervolging breekt. Omdat de ruimte moeilijk te zien is, kan het lastig zijn om de fout te vinden.

PowerShell biedt verschillende manieren waarop regels worden onderbroken op natuurlijke punten in de syntaxis.

  • Na sluistekens (|)
  • Na binaire operatoren (+, -, -eq, enzovoort)
  • Na komma's (,) in een matrix
  • Na het openen van tekens, zoals [, {(

Voor grote parameterset gebruikt u in plaats daarvan splatting. Bijvoorbeeld:

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

Argumenten doorgeven aan systeemeigen opdrachten

Bij het uitvoeren van systeemeigen opdrachten vanuit PowerShell worden de argumenten eerst geparseerd door PowerShell. De geparseerde argumenten worden vervolgens samengevoegd in één tekenreeks waarbij elke parameter wordt gescheiden door een spatie.

Met de volgende opdracht wordt het icacls.exe programma bijvoorbeeld aangeroepen.

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

Als u deze opdracht wilt uitvoeren in PowerShell 2.0, moet u escape-tekens gebruiken om te voorkomen dat PowerShell de haakjes verkeerd interpreteert.

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

Het token voor stoppen met parseren

Vanaf PowerShell 3.0 kunt u het token stoppen-parseren (--%) gebruiken om te voorkomen dat PowerShell invoer interpreteert als PowerShell-opdrachten of -expressies.

Notitie

Het stop-parsing-token is alleen bedoeld voor het gebruik van systeemeigen opdrachten op Windows-platforms.

Wanneer u een systeemeigen opdracht aanroept, plaatst u het stop-parsing-token vóór de programmaargumenten. Deze techniek is veel eenvoudiger dan het gebruik van escape-tekens om onjuiste interpretatie te voorkomen.

Wanneer er een stopparseringstoken wordt aantreft, worden de resterende tekens in de regel door PowerShell als letterlijk behandeld. De enige interpretatie die wordt uitgevoerd, is het vervangen van waarden voor omgevingsvariabelen die gebruikmaken van de standaard Windows-notatie, zoals %USERPROFILE%.

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

PowerShell verzendt de volgende opdrachtreeks naar het icacls.exe programma:

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

Het stop-parsing-token is alleen geldig tot het volgende nieuwe regel- of pijplijnteken. U kunt het regelvervolgteken (`) niet gebruiken om het effect ervan uit te breiden of een opdrachtscheidingsteken (;) gebruiken om het effect te beëindigen.

%variable% Behalve verwijzingen naar omgevingsvariabelen kunt u geen andere dynamische elementen insluiten in de opdracht. Het ontsnappen van een % teken als %%, zoals u dat in batchbestanden kunt doen, wordt niet ondersteund. %<name>% tokens worden steevast uitgevouwen. Als <name> niet verwijst naar een gedefinieerde omgevingsvariabele, wordt het token als zodanig doorgegeven.

U kunt geen stream-omleiding (zoals >file.txt) gebruiken, omdat ze letterlijk als argumenten worden doorgegeven aan de doelopdracht.

In het volgende voorbeeld wordt met de eerste stap een opdracht uitgevoerd zonder het stop-parsing-token te gebruiken. PowerShell evalueert de tekenreeks met aanhalingstekens en geeft de waarde (zonder aanhalingstekens) door aan cmd.exe, wat resulteert in een fout.

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"

Notitie

Het stop-parsing-token is niet nodig wanneer u PowerShell-cmdlets gebruikt. Het kan echter handig zijn om argumenten door te geven aan een PowerShell-functie die is ontworpen om een systeemeigen opdracht aan te roepen met deze argumenten.

Argumenten doorgeven die aanhalingstekens bevatten

Sommige systeemeigen opdrachten verwachten argumenten die aanhalingstekens bevatten. PowerShell 7.3 heeft de manier gewijzigd waarop de opdrachtregel wordt geparseerd voor systeemeigen opdrachten.

Waarschuwing

Het nieuwe gedrag is een belangrijke wijziging van het Gedrag van Windows PowerShell 5.1. Hierdoor kunnen scripts en automatisering worden onderbroken die de verschillende problemen omzeilen bij het aanroepen van systeemeigen toepassingen. Gebruik het stop-parsing-token (--%) of de Start-Process cmdlet om te voorkomen dat het systeemeigen argument wordt doorgegeven wanneer dat nodig is.

De nieuwe $PSNativeCommandArgumentPassing voorkeursvariabele bepaalt dit gedrag. Met deze variabele kunt u het gedrag tijdens runtime selecteren. De geldige waarden zijn Legacy, Standarden Windows. Het standaardgedrag is platformspecifiek. Op Windows-platforms is Windows de standaardinstelling en niet-Windows-platforms zijn standaard ingesteld op Standard.

Legacy is het historische gedrag. Het gedrag van Windows de modus en Standard is hetzelfde, behalve dat in Windows de modus aanroepen van de volgende bestanden automatisch het Legacy stijlargument gebruiken dat wordt doorgegeven.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • eindigend op .bat
  • eindigend op .cmd
  • eindigend op .js
  • eindigend op .vbs
  • eindigend op .wsf

Als de $PSNativeCommandArgumentPassing is ingesteld op Legacy of Standard, controleert de parser niet op deze bestanden.

Notitie

In de volgende voorbeelden wordt het TestExe.exe hulpprogramma gebruikt. U kunt bouwen TestExe op basis van de broncode. Zie TestExe in de PowerShell-bronopslagplaats.

Nieuw gedrag dat beschikbaar is gemaakt door deze wijziging:

  • Letterlijke of uitbreidbare tekenreeksen met ingesloten aanhalingstekens. De aanhalingstekens blijven nu behouden:

    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>
    
  • Lege tekenreeksen als argumenten blijven nu behouden:

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

Het doel van deze voorbeelden is om het mappad (met spaties en aanhalingstekens) "C:\Program Files (x86)\Microsoft\" door te geven aan een systeemeigen opdracht, zodat het pad als een tekenreeks met aanhalingstekens wordt ontvangen.

In Windows de modus of Standard leveren de volgende voorbeelden de verwachte resultaten op:

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

Als u in de modus dezelfde resultaten Legacy wilt krijgen, moet u de aanhalingstekens laten ontsnappen of het token voor het parseren van de aanhalingstekens gebruiken (--%):

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

Notitie

Het backslashteken (\) wordt niet herkend als een escape-teken door PowerShell. Dit is het escape-teken dat wordt gebruikt door de onderliggende API voor ProcessStartInfo.ArgumentList.

PowerShell 7.3 heeft ook de mogelijkheid toegevoegd om parameterbinding te traceren voor systeemeigen opdrachten. Zie Trace-Command voor meer informatie.

Argumenten doorgeven aan PowerShell-opdrachten

Vanaf PowerShell 3.0 kunt u het token end-of-parameters (--) gebruiken om te voorkomen dat PowerShell invoer interpreteert als PowerShell-parameters. Dit is een conventie die is opgegeven in de specificatie POSIX Shell en Utilities.

Het einde-van-parameters-token

Het einde-van-parameterstoken (--) geeft aan dat alle argumenten die erop volgen, in hun werkelijke vorm moeten worden doorgegeven alsof er dubbele aanhalingstekens om de aanhalingstekens zijn geplaatst. Met behulp van -- kunt u de tekenreeks -InputObject bijvoorbeeld uitvoeren zonder aanhalingstekens te gebruiken of deze te laten interpreteren als een parameter:

Write-Output -- -InputObject
-InputObject

In tegenstelling tot het token stop-parsing (--%), kunnen alle waarden na het -- token worden geïnterpreteerd als expressies door PowerShell.

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

Dit gedrag is alleen van toepassing op PowerShell-opdrachten. Als u het -- token gebruikt bij het aanroepen van een externe opdracht, wordt de -- tekenreeks als argument doorgegeven aan die opdracht.

TestExe -echoargs -a -b -- -c

De uitvoer laat zien dat -- als argument wordt doorgegeven aan TestExe.

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

Tilde (~)

Het tildeteken (~) heeft een speciale betekenis in PowerShell. Wanneer het wordt gebruikt met PowerShell-opdrachten aan het begin van een pad, wordt het tilde-teken uitgevouwen naar de basismap van de gebruiker. Als het tilde-teken ergens anders in een pad wordt gebruikt, wordt het beschouwd als een letterlijk teken.

PS D:\temp> $PWD

Path
----
D:\temp

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

Path
----
C:\Users\user2

In dit voorbeeld verwacht de parameter Name van de New-Item een tekenreeks. Het tildeteken wordt behandeld als een letterlijk teken. Als u wilt overschakelen naar de zojuist gemaakte map, moet u het pad kwalificeren met het tilde-teken.

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

Wanneer u het tilde-teken gebruikt met systeemeigen opdrachten, geeft PowerShell de tilde door als een letterlijk teken. Het gebruik van de tilde in een pad veroorzaakt fouten voor systeemeigen opdrachten in Windows die het tilde-teken niet ondersteunen.

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

Zie ook