Freigeben über


Über_Parsing

Kurzbeschreibung

Beschreibt, wie PowerShell Befehle analysiert.

Lange Beschreibung

Wenn Sie an der Eingabeaufforderung einen Befehl eingeben, bricht PowerShell den Befehlstext in eine Reihe von Segmenten auf, die Token genannt werden, und bestimmt dann, wie jedes Token interpretiert werden soll.

Wenn Sie beispielsweise Folgendes eingeben:

Write-Host book

PowerShell unterteilt den Befehl in zwei Token, Write-Host und book, und interpretiert jedes Token unabhängig von einem von zwei hauptanalysemodi: Ausdrucksmodus und Argumentmodus.

Hinweis

Da PowerShell Befehlseingaben analysiert, versucht sie, die Befehlsnamen in Cmdlets oder systemeigene ausführbare Dateien aufzulösen. Wenn ein Befehlsname keine genaue Übereinstimmung aufweist, fügt PowerShell standardmäßig Get- als Verb vor den Befehl hinzu. PowerShell analysiert z. B. Service als Get-Service. Es wird nicht empfohlen, dieses Feature aus den folgenden Gründen zu verwenden:

  • Es ist ineffizient. Dies führt dazu, dass PowerShell mehrmals sucht.
  • Externe Programme mit demselben Namen werden zuerst aufgelöst, sodass Sie das beabsichtigte Cmdlet möglicherweise nicht ausführen.
  • Get-Help und Get-Command erkennen keine verblosen Namen.
  • Der Befehlsname kann ein reserviertes Wort oder ein Sprachstichwort sein. Process ist beides und kann nicht in Get-Processaufgelöst werden.

Ausdrucksmodus

Der Ausdrucksmodus dient zum Kombinieren von Ausdrücken, die für die Wertmanipulation in einer Skriptsprache erforderlich sind. Ausdrücke sind Darstellungen von Werten in der PowerShell-Syntax und können einfach oder zusammengesetzt sein, z. B.:

Literale Ausdrücke sind direkte Darstellungen ihrer Werte:

'hello'
32

Variable Ausdrücke tragen den Wert der Variablen, auf die sie verweisen:

$x
$script:path

Operatoren kombinieren andere Ausdrücke für die Auswertung:

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • Zeichenfolgen-Literale müssen in Anführungszeichen gesetzt werden.
  • Zahlen werden als numerische Werte und nicht als eine Reihe von Zeichen behandelt (sofern sie nicht escaped sind).
  • Operatoren, einschließlich unärer Operatoren wie - und -not und binäre Operatoren wie + und -gt, werden als Operatoren interpretiert und ihre jeweiligen Vorgänge auf ihre Argumente (Operanden) angewendet.
  • Attribut- und Konvertierungsausdrücke werden als Ausdrücke analysiert und auf untergeordnete Ausdrücke angewendet. Beispiel: [int] '7'.
  • Variablenreferenzen werden zu ihren Werten ausgewertet, aber Splatting ist verboten und verursacht einen Parserfehler.
  • Alles andere wird als befehl behandelt, der aufgerufen werden soll.

Diskussionsmodus

Beim Analysieren sucht PowerShell zunächst, eingaben als Ausdruck zu interpretieren. Wenn jedoch ein Befehlsaufruf auftritt, wird die Analyse im Argumentmodus fortgesetzt. Wenn Sie Argumente haben, die Leerzeichen enthalten, z. B. Pfade, müssen Sie diese Argumentwerte in Anführungszeichen setzen.

Der Argumentmodus wurde für die Analyse von Argumenten und Parametern für Befehle in einer Shellumgebung entwickelt. Alle Eingaben werden als erweiterbare Zeichenfolge behandelt, es sei denn, sie verwendet eine der folgenden Syntaxen:

  • Dollarzeichen ($) gefolgt von einem Variablennamen beginnt einen Variablenverweis, andernfalls wird es als Teil der erweiterbaren Zeichenfolge interpretiert. Die Variablenreferenz kann einen Mitgliedszugriff oder eine Indizierung beinhalten.

    • Zusätzliche Zeichen nach einfachen Variablenverweisen, wie z. B. $HOME, werden als Teil desselben Arguments betrachtet. Schließen Sie den Variablennamen in geschweifte Klammern ({}) ein, um ihn von nachfolgenden Zeichen zu trennen. Beispiel: ${HOME}.
    • Wenn die Variablenreferenz einen Mitgliedszugriff enthält, wird das erste aller zusätzlichen Zeichen als Beginn eines neuen Arguments betrachtet. Zum Beispiel ergibt $HOME.Length-more zwei Argumente: den Wert von $HOME.Length und die Zeichenfolge -more.
  • Anführungszeichen (' und ") beginnen Zeichenfolgen

  • Klammern ({}) beginnen eine neue Skriptblockierung

  • Kommas (,) führen Listen ein, die als Arrays übergeben werden, es sei denn, der aufgerufene Befehl ist eine systemeigene Anwendung, in diesem Fall werden sie als Teil der erweiterbaren Zeichenfolge interpretiert. Anfängliche, aufeinander folgende oder nachfolgende Kommas werden nicht unterstützt.

  • Klammern (()) beginnen einen neuen Ausdruck

  • Der Subexpression-Operator ($()) beginnt einen eingebetteten Ausdruck.

  • Das anfängliche at-Zeichen (@) beginnt Ausdrucksschreibweisen wie z. B. Splatting (@args), Arrays (@(1,2,3)) und Hash-Tabellen-Literale (@{a=1;b=2}).

  • (), $()und @() am Anfang eines Tokens erstellen einen neuen Analysekontext, der Ausdrücke oder geschachtelte Befehle enthalten kann.

    • Gefolgt von zusätzlichen Zeichen wird das erste zusätzliche Zeichen als Beginn eines neuen, separaten Arguments betrachtet.
    • Wenn ein nicht in Anführungszeichen gesetztes Literal vorangestellt ist, funktioniert $() wie eine erweiterbare Zeichenfolge, () beginnt ein neues Argument, das ein Ausdruck ist, und @() wird als Literal @ betrachtet, wobei () ein neues Argument beginnt, das ein Ausdruck ist.
  • Alles andere wird wie eine erweiterbare Zeichenfolge behandelt, mit Ausnahme von Metazeichen, die immer noch mit Escaping versehen werden müssen. Siehe Umgang mit Sonderzeichen.

    • Die Argumentmodus-Metacharacter (Zeichen mit spezieller syntaktischer Bedeutung) sind: <space> ' " ` , ; ( ) { } | & < > @ #. Von diesen sind < > @ # nur am Anfang eines Tokens besonders.
  • Das Stoppanalysetoken (--%) ändert die Interpretation aller verbleibenden Argumente. Weitere Informationen finden Sie unter stop-parsing Token unten.

Beispiele

Die folgende Tabelle enthält mehrere Beispiele für Token, die im Ausdrucksmodus und im Argumentmodus verarbeitet werden, und die Auswertung dieser Token. Für diese Beispiele ist der Wert der Variablen $a4.

Beispiel Modus Ergebnis
2 Ausdruck 2 (ganze Zahl)
`2 Ausdruck "2" (Befehl)
Write-Output 2 Ausdruck 2 (ganze Zahl)
2+2 Ausdruck 4 (ganze Zahl)
Write-Output 2+2 Streitpunkt "2+2" (Zeichenfolge)
Write-Output(2+2) Ausdruck 4 (ganze Zahl)
$a Ausdruck 4 (ganze Zahl)
Write-Output $a Ausdruck 4 (ganze Zahl)
$a+2 Ausdruck 6 (ganze Zahl)
Write-Output $a+2 Streitpunkt "4+2" (Zeichenfolge)
$- Streitpunkt "$-" (Befehl)
Write-Output $- Streitpunkt "$-" (Zeichenfolge)
a$a Ausdruck "a$a" (Befehl)
Write-Output a$a Streitpunkt "a4" (Zeichenfolge)
a'$a' Ausdruck "a$a" (Befehl)
Write-Output a'$a' Streitpunkt "a$a" (Zeichenfolge)
a"$a" Ausdruck "a$a" (Befehl)
Write-Output a"$a" Streitpunkt "a4" (Zeichenfolge)
a$(2) Ausdruck "a$(2)" (Befehl)
Write-Output a$(2) Streitpunkt "a2" (Zeichenfolge)

Jedes Token kann als eine Art objekttyp interpretiert werden, z. B. boolesche oder String-. PowerShell versucht, den Objekttyp aus dem Ausdruck zu ermitteln. Der Objekttyp hängt vom Typ des Parameters ab, den ein Befehl erwartet, und ob PowerShell weiß, wie das Argument in den richtigen Typ konvertiert werden kann. Die folgende Tabelle enthält mehrere Beispiele für die Typen, die den von den Ausdrücken zurückgegebenen Werten zugewiesen werden.

Beispiel Modus Ergebnis
Write-Output !1 Streit "!1" (Zeichenfolge)
Write-Output (!1) Ausdruck FALSE (boolesch)
Write-Output (2) Ausdruck 2 (ganze Zahl)
Set-Variable AB A,B Streit A','B' (Array)
CMD /CECHO A,B Streit A,B' (Zeichenfolge)
CMD /CECHO $AB Ausdruck A B' (Array)
CMD /CECHO :$AB Streit :A B' (Zeichenfolge)

Verarbeiten von Sonderzeichen

Das Backtick-Zeichen (`) kann verwendet werden, um jedes Sonderzeichen in einem Ausdruck zu umgehen. Dies ist besonders nützlich, wenn Sie die Metazeichen des Argumentmodus, die Sie als Literalzeichen und nicht als Metazeichen verwenden möchten, ausblenden möchten. Um beispielsweise das Dollarzeichen ($) als Literal in einer erweiterbaren Zeichenfolge zu verwenden:

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

Zeilenfortsetzung

Das Backtick-Zeichen kann auch am Ende einer Zeile verwendet werden, damit Sie die Eingabe in der nächsten Zeile fortsetzen können. Dies verbessert die Lesbarkeit eines Befehls, der mehrere Parameter mit langen Namen und Argumentwerten verwendet. Beispiel:

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

Sie sollten jedoch vermeiden, die Zeilenfortsetzung zu verwenden.

  • Die Backtick-Zeichen können schwer zu sehen und leicht zu vergessen sein.
  • Ein zusätzliches Leerzeichen nach dem Backtick unterbricht die Zeilenfortsetzung fehlerhaft. Da der Platz schwer zu erkennen ist, kann es schwierig sein, den Fehler zu finden.

PowerShell bietet mehrere Möglichkeiten, Zeilen an natürlichen Punkten in der Syntax umzubrechen.

  • Nach Pipe-Zeichen (|)
  • Nach binären Operatoren (+, -, -equsw.)
  • Nach Kommas (,) in einem Array
  • Nach Eröffnungszeichen wie z. B. [, {, (

Verwenden Sie bei einem großen Set von Parametern stattdessen Splatting. Beispiel:

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

Übergeben von Argumenten an native Befehle

Wenn Systemeigene Befehle aus PowerShell ausgeführt werden, werden die Argumente zuerst von PowerShell analysiert. Die analysierten Argumente werden dann mit einer einzelnen Zeichenfolge verknüpft, wobei jeder Parameter durch ein Leerzeichen getrennt ist.

Beispielsweise ruft der folgende Befehl das icacls.exe Programm auf.

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

Um diesen Befehl in PowerShell 2.0 auszuführen, müssen Sie Escapezeichen verwenden, um zu verhindern, dass PowerShell die Klammern falsch interpretiert.

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

Das stop-parsing Token

Ab PowerShell 3.0 können Sie das Stoppanalysetoken (--%) verwenden, um zu verhindern, dass PowerShell Eingaben als PowerShell-Befehle oder -Ausdrücke interpretiert.

Hinweis

Das stop-parsing Token ist nur für die Verwendung nativer Befehle auf Windows-Plattformen vorgesehen.

Platzieren Sie beim Aufrufen eines nativen Befehls das Stopp-Parsing-Token vor den Programmargumenten. Diese Technik ist viel einfacher als die Verwendung von Escapezeichen, um Fehlinterpretation zu verhindern.

Wenn PowerShell auf ein stop-parsing Token stößt, behandelt es die verbleibenden Zeichen in der Zeile als ein Literal. Die einzige Interpretation, die sie ausführt, besteht darin, Werte für Umgebungsvariablen zu ersetzen, die die standardmäßige Windows-Schreibweise verwenden, z. B. %USERPROFILE%.

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

PowerShell sendet die folgende Befehlszeichenfolge an das icacls.exe Programm:

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

Das Stop-Parsing-Token ist nur bis zum nächsten Zeilenumbruch oder Pipeline-Zeichen wirksam. Sie können das Zeilenfortsetzungszeichen (`) nicht verwenden, um den Effekt zu erweitern oder ein Befehlstrennzeichen (;) zum Beenden des Effekts zu verwenden.

Abgesehen von %variable%-Umgebungsvariablenverweisen können Sie keine anderen dynamischen Elemente in den Befehl einbetten. Das Escapen eines %-Zeichens als %%, wie Sie es in Batch-Dateien tun können, wird nicht unterstützt. %<name>% Token werden ausnahmslos erweitert. Wenn <name> nicht auf eine definierte Umgebungsvariable verweist, wird das Token über as-isübergeben.

Sie können die Umleitung von Streams (wie >file.txt) nicht verwenden, da sie wörtlich als Argumente an den Zielbefehl übergeben werden.

Im folgenden Beispiel führt der erste Schritt einen Befehl aus, ohne das Stop-Parsing-Token zu verwenden. PowerShell wertet die Zeichenfolge aus und übergibt den Wert (ohne Anführungszeichen) an cmd.exe, was zu einem Fehler führt.

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"

Hinweis

Das Stoppanalysetoken ist bei Verwendung von PowerShell-Cmdlets nicht erforderlich. Es kann jedoch hilfreich sein, Argumente an eine PowerShell-Funktion zu übergeben, die zum Aufrufen eines systemeigenen Befehls mit diesen Argumenten konzipiert ist.

Übergabe von Argumenten, die Anführungszeichen enthalten

Einige native Befehle erwarten Argumente, die Anführungszeichen enthalten. PowerShell 7.3 hat die Art und Weise geändert, wie die Befehlszeile für systemeigene Befehle analysiert wird.

Vorsicht

Das neue Verhalten ist eine wichtige Änderung gegenüber dem Verhalten von Windows PowerShell 5.1. Dies kann Skripte und Automatisierungen unterbrechen, die beim Aufrufen nativer Anwendungen verschiedene Probleme umgehen. Verwenden Sie das Stop-Parsing-Token (--%) oder das cmdlet Start-Process, um zu vermeiden, dass das systemeigene Argument bei Bedarf übergeben wird.

Die neue $PSNativeCommandArgumentPassing Einstellungsvariable steuert dieses Verhalten. Mit dieser Variablen können Sie das Verhalten zur Laufzeit auswählen. Die gültigen Werte sind Legacy, Standardund Windows. Das Standardverhalten ist plattformspezifisch. Auf Windows-Plattformen ist die Standardeinstellung Windows und Nicht-Windows-Plattformen standardmäßig auf Standardfestgelegt.

Legacy ist das historische Verhalten. Das Verhalten der Modi Windows und Standard ist identisch, mit Ausnahme, dass im Windows-Modus die Aufrufe der folgenden Dateien automatisch die Legacy-Stilargumentübergabe verwenden.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • enden mit .bat
  • enden mit .cmd
  • enden mit .js
  • enden mit .vbs
  • enden mit .wsf

Wenn die $PSNativeCommandArgumentPassing entweder auf Legacy oder Standardfestgelegt ist, sucht der Parser nicht nach diesen Dateien.

Hinweis

In den folgenden Beispielen wird das tool TestExe.exe verwendet. Sie können TestExe aus dem Quellcode erstellen. Siehe TestExe- im PowerShell-Quell-Repository.

Neue Verhaltensweisen, die von dieser Änderung zur Verfügung gestellt werden:

  • In literalen oder erweiterbaren Zeichenfolgen mit eingebetteten Anführungszeichen werden die Anführungszeichen jetzt beibehalten:

    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>
    
  • Leere Zeichenfolgen als Argumente bleiben jetzt erhalten:

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

Ziel dieser Beispiele ist es, den Verzeichnispfad (mit Leerzeichen und Anführungszeichen) "C:\Program Files (x86)\Microsoft\" an einen systemeigenen Befehl zu übergeben, damit er den Pfad als Zeichenfolge mit Anführungszeichen empfangen hat.

Im Windows- oder Standard-Modus erzeugen die folgenden Beispiele die erwarteten Ergebnisse:

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

Um die gleichen Ergebnisse im Modus Legacy zu erhalten, müssen Sie die Anführungszeichen maskieren oder das Stop-Parsing-Token verwenden (--%):

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

Hinweis

Das Backslash-Zeichen (\) wird von der PowerShell nicht als Escape-Zeichen erkannt. Es ist das Escape-Zeichen, das von der zugrunde liegenden API für ProcessStartInfo.ArgumentList verwendet wird.

PowerShell 7.3 hat auch die Möglichkeit zum Nachverfolgen der Parameterbindung für systemeigene Befehle hinzugefügt. Weitere Informationen finden Sie unter Trace-Command.

Übergabe von Argumenten an PowerShell-Befehle

Ab PowerShell 3.0 können Sie das End-of-Parameters--Token (--) verwenden, um zu verhindern, dass PowerShell Eingaben als PowerShell-Parameter interpretiert. Dies ist eine Konvention, die in der POSIX Shell and Utilities-Spezifikation angegeben ist.

Das Token für das Ende von Parametern

Das End-of-Parameters-Token (--) gibt an, dass alle darauf folgenden Argumente in ihrer tatsächlichen Form übergeben werden sollen, als ob doppelte Anführungszeichen um sie herum platziert wurden. Wenn Sie z. B. -- verwenden, können Sie die Zeichenfolge -InputObject ausgeben, ohne Anführungszeichen zu verwenden oder als Parameter interpretiert zu haben:

Write-Output -- -InputObject
-InputObject

Im Gegensatz zum Stop-Parsing(--%)-Token können alle Werte, die dem -- Token folgen, von PowerShell als Ausdrücke interpretiert werden.

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

Dieses Verhalten gilt nur für PowerShell-Befehle. Wenn Sie das ---Token beim Aufrufen eines externen Befehls verwenden, wird die -- Zeichenfolge als Argument an diesen Befehl übergeben.

TestExe -echoargs -a -b -- -c

Die Ausgabe zeigt, dass -- als Argument an TestExeübergeben wird.

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

Tilde (~)

Das Tildezeichen (~) hat in PowerShell eine besondere Bedeutung. Wenn sie mit PowerShell-Befehlen am Anfang eines Pfads verwendet wird, wird das Tildezeichen in das Startverzeichnis des Benutzers erweitert. Wenn das Tildezeichen an einer anderen Stelle in einem Pfad verwendet wird, wird es als Literalzeichen behandelt.

PS D:\temp> $PWD

Path
----
D:\temp

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

Path
----
C:\Users\user2

In diesem Beispiel erwartet der parameter Name des New-Item eine Zeichenfolge. Das Tilde-Zeichen wird als literales Zeichen behandelt. Um in das neu erstellte Verzeichnis zu wechseln, müssen Sie den Pfad mit dem Tildezeichen qualifizieren.

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

Wenn Sie das Tildezeichen mit systemeigenen Befehlen verwenden, übergibt PowerShell die Tilde als Literalzeichen. Die Verwendung der Tilde in einem Pfad verursacht Fehler für systemeigene Befehle unter Windows, die das Tildezeichen nicht unterstützen.

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

Siehe auch