Freigeben über


about_Parsing

Kurze Beschreibung

Beschreibt, wie PowerShell Befehle analysiert.

Lange Beschreibung

Wenn Sie einen Befehl an der Eingabeaufforderung eingeben, unterbricht PowerShell den Befehlstext in eine Reihe von Segmenten, die als Token bezeichnet werden, und bestimmt dann, wie die einzelnen Token interpretiert werden.

Wenn Sie beispielsweise Folgendes eingeben:

Write-Host book

PowerShell unterbricht den Befehl in zwei Token, Write-Host und bookinterpretiert jedes Token unabhängig von einem von zwei Hauptanalysemodi: Ausdrucksmodus und Argumentmodus.

Hinweis

Wenn PowerShell Befehlseingaben analysiert, versucht es, die Befehlsnamen in Cmdlets oder native ausführbare Dateien aufzulösen. Wenn ein Befehlsname keine genaue Übereinstimmung aufweist, wird der Befehl von PowerShell als Standardverb vorangestellt Get- . PowerShell analysiert Service beispielsweise als Get-Service. Es wird aus den folgenden Gründen nicht empfohlen, dieses Feature zu verwenden:

  • Dies ist ineffizient. Dies führt dazu, dass PowerShell mehrmals durchsucht.
  • Externe Programme mit demselben Namen werden zuerst aufgelöst, sodass Sie das beabsichtigte Cmdlet möglicherweise nicht ausführen.
  • Get-Help und Get-Command keine Namen ohne Verben erkennen.
  • Der Befehlsname kann ein reserviertes Wort oder eine Sprache Schlüsselwort (keyword) 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 Wertbearbeitung in einer Skriptsprache erforderlich sind. Ausdrücke sind Darstellungen von Werten in der PowerShell-Syntax und können einfach oder zusammengesetzt sein, z. B.:

Literalausdrücke sind direkte Darstellungen ihrer Werte:

'hello'
32

Variablenausdrü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
  • Zeichenfolgenliterale müssen in Anführungszeichen enthalten sein.
  • Zahlen werden als numerische Werte und nicht als Eine Reihe von Zeichen behandelt (es sei denn, es wird ein Escapezeichen gesetzt).
  • Operatoren, einschließlich unärer Operatoren wie - und -not und binäre Operatoren wie + und -gt, werden als Operatoren interpretiert und wenden ihre jeweiligen Operationen auf ihre Argumente (Operanden) an.
  • Attribut- und Konvertierungsausdrücke werden als Ausdrücke analysiert und auf untergeordnete Ausdrücke angewendet. Beispiel: [int] '7'.
  • Variablenverweise werden anhand ihrer Werte ausgewertet, das Splatting ist jedoch verboten und verursacht einen Parserfehler.
  • Alles andere wird als befehl behandelt, der aufgerufen werden soll.

Argumentmodus

Bei der Analyse versucht 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 einschließen.

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

  • Das Dollarzeichen ($) gefolgt von einem Variablennamen beginnt einen Variablenverweis, andernfalls wird es als Teil der erweiterbaren Zeichenfolge interpretiert. Der Variablenverweis kann den Memberzugriff oder die Indizierung umfassen.

    • Zusätzliche Zeichen, die auf einfache Variablenverweise folgen, z $HOME. B. , 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 der Variablenverweis den Memberzugriff einschließt, wird das erste zusätzliche Zeichen als Anfang eines neuen Arguments betrachtet. Führt beispielsweise $HOME.Length-more zu zwei Argumenten: dem Wert von und dem $HOME.Length Zeichenfolgenliteral -more.
  • Anführungszeichen (' und ") beginnen Zeichenfolgen

  • Geschweifte Klammern ({}) beginnen mit neuen Skriptblöcken

  • Kommas (,) führen Listen ein, die als Arrays übergeben werden, es sei denn, der aufgerufene Befehl ist eine native 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

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

  • Initial at sign (@) beginnt mit Ausdruckssyntaxen wie Splatting (@args), Arrays (@(1,2,3)) und Hashtabellenliteralen (@{a=1;b=2}).

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

    • Wenn zusätzliche Zeichen folgen, wird das erste zusätzliche Zeichen als Anfang eines neuen, separaten Arguments betrachtet.
    • Wenn ein Literal $() ohne Anführungszeichen vorangestellt wird, funktioniert wie eine erweiterbare Zeichenfolge, () startet ein neues Argument, das ein Ausdruck ist, und @() wird als Literal @ verwendet, indem () ein neues Argument gestartet wird, das ein Ausdruck ist.
  • Alles andere wird als erweiterbare Zeichenfolge behandelt, mit Ausnahme von Metazeichen, die noch escapen müssen. Weitere Informationen finden Sie unter Behandeln von Sonderzeichen.

    • Die Metazeichen im Argumentmodus (Zeichen mit besonderer syntaktischer Bedeutung) sind: <space> ' " ` , ; ( ) { } | & < > @ #. Von diesen < > @ # sind nur am Anfang eines Tokens besonders.
  • Das Token für die Stoppanalyse (--%) ändert die Interpretation aller verbleibenden Argumente. Weitere Informationen finden Sie weiter unten im Abschnitt zum Beenden des Analysetokens .

Beispiele

Die folgende Tabelle enthält mehrere Beispiele für Token, die im Ausdrucks- und Argumentmodus verarbeitet werden, und die Auswertung dieser Token. In diesen Beispielen ist 4der Wert der Variablen $a .

Beispiel Mode 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 Argument "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 Argument "4+2" (Zeichenfolge)
$- Argument "$-" (Befehl)
Write-Output $- Argument "$-" (Zeichenfolge)
a$a Ausdruck "a$a" (Befehl)
Write-Output a$a Argument "a4" (Zeichenfolge)
a'$a' Ausdruck "a$a" (Befehl)
Write-Output a'$a' Argument "a$a" (Zeichenfolge)
a"$a" Ausdruck "a$a" (Befehl)
Write-Output a"$a" Argument "a4" (Zeichenfolge)
a$(2) Ausdruck "a$(2)" (Befehl)
Write-Output a$(2) Argument "a2" (Zeichenfolge)

Jedes Token kann als eine Art von Objekttyp interpretiert werden, z. B. Boolean oder String. PowerShell versucht, den Objekttyp aus dem Ausdruck zu bestimmen. Der Objekttyp hängt vom Typ des Parameters ab, den ein Befehl erwartet, und davon, 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 Werten zugewiesen sind, die von den Ausdrücken zurückgegeben werden.

Beispiel Mode Ergebnis
Write-Output !1 Argument "!1" (Zeichenfolge)
Write-Output (!1) expression False (Boolescher Wert)
Write-Output (2) expression 2 (ganze Zahl)
Set-Variable AB A,B Argument 'A','B' (Array)
CMD /CECHO A,B Argument "A,B" (Zeichenfolge)
CMD /CECHO $AB expression "A B" (Array)
CMD /CECHO :$AB Argument ':A B' (Zeichenfolge)

Behandeln von Sonderzeichen

Das Backtick-Zeichen (`) kann verwendet werden, um ein beliebiges Sonderzeichen in einem Ausdruck mit Escapezeichen zu versehen. Dies ist besonders nützlich, um die Metazeichen im Argumentmodus zu escapen, die Sie als Literalzeichen und nicht als Metazeichen verwenden möchten. So verwenden Sie beispielsweise das Dollarzeichen ($) als Literal in einer erweiterbaren Zeichenfolge:

"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. Dadurch wird die Lesbarkeit eines Befehls verbessert, der mehrere Parameter mit langen Namen und Argumentwerten akzeptiert. Beispiel:

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

Sie sollten jedoch die Verwendung der Zeilenfortsetzung vermeiden.

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

PowerShell bietet mehrere Möglichkeiten, um Linien an natürlichen Punkten in der Syntax zu unterbrechen.

  • After-Pipe-Zeichen (|)
  • Nach binären Operatoren (+, -, -equsw.)
  • Nach Kommas (,) in einem Array
  • Nach dem Öffnen von Zeichen wie [, {, (

Verwenden Sie für einen großen Parametersatz 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

Beim Ausführen nativer Befehle über PowerShell werden die Argumente zuerst von PowerShell analysiert. Die analysierten Argumente werden dann in einer einzelnen Zeichenfolge verknüpft, wobei jeder Parameter durch ein Leerzeichen getrennt ist.

Der folgende Befehl ruft beispielsweise 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 Token für die Stoppanalyse

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

Hinweis

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

Wenn Sie einen nativen Befehl aufrufen, platzieren Sie das Token für die Stoppanalyse vor den Programmargumenten. Diese Technik ist viel einfacher als die Verwendung von Escapezeichen, um Fehlinterpretationen zu verhindern.

Wenn ein Token für die Stoppanalyse auftritt, behandelt PowerShell die verbleibenden Zeichen in der Zeile als Literal. Die einzige Interpretation, die ausgeführt wird, besteht darin, Werte für Umgebungsvariablen zu ersetzen, die die Windows-Standardnotation verwenden, z %USERPROFILE%. B. .

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 Token für die Stoppanalyse ist nur bis zum nächsten Zeilenumbruch- oder Pipelinezeichen wirksam. Sie können das Zeilenfortsetzungszeichen (`) nicht verwenden, um seine Wirkung zu erweitern, oder ein Befehlstrennzeichen (;) verwenden, um seine Wirkung zu beenden.

Abgesehen von %variable% Umgebungsvariablen-Verweisen können Sie keine anderen dynamischen Elemente in den Befehl einbetten. Das Escapen eines % Zeichens als %%, wie Sie dies in Batchdateien tun können, wird nicht unterstützt. %<name>% Token werden immer erweitert. Wenn <name> nicht auf eine definierte Umgebungsvariable verweist, wird das Token unverändert übergeben.

Sie können die Streamumleitung (z >file.txt. B. ) nicht verwenden, da sie wortwörtlich als Argumente an den Zielbefehl übergeben werden.

Im folgenden Beispiel wird im ersten Schritt ein Befehl ausgeführt, ohne das Token für die Stoppanalyse zu verwenden. PowerShell wertet die Zeichenfolge in Anführungszeichen aus und übergibt den Wert (ohne Anführungszeichen) an , was zu cmd.exeeinem 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 Token für die Stoppanalyse wird bei Verwendung von PowerShell-Cmdlets nicht benötigt. Es kann jedoch hilfreich sein, Argumente an eine PowerShell-Funktion zu übergeben, die zum Aufrufen eines nativen Befehls mit diesen Argumenten entwickelt wurde.

Übergeben 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 native Befehle analysiert wird.

Achtung

Das neue Verhalten ist eine Breaking Change gegenüber dem Windows PowerShell 5.1-Verhalten. Dadurch kann es geschehen, dass Skripts und Automatisierungen zum Umgehen der verschiedenen Probleme beim Aufrufen nativer Anwendungen nicht mehr funktionieren. Verwenden Sie das Stop-Parsing-Token (--%) oder das Start-Process Cmdlet, um zu vermeiden, dass das systemeigene Argument bei Bedarf übergeben wird.

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

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
  • Endet mit .bat
  • Endet mit .cmd
  • Endet mit .js
  • Endet mit .vbs
  • Endet mit .wsf

Wenn $PSNativeCommandArgumentPassing auf Legacy oder Standard festgelegt ist, überprüft der Parser keine diese Dateien.

Hinweis

In den folgenden Beispielen wird das TestExe.exe-Tool verwendet. Sie können TestExe aus dem Quellcode erstellen. Weitere Informationen finden Sie unter TestExe im PowerShell-Quellrepository.

Neue Verhaltensweisen, die durch diese Änderung verfügbar gemacht 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 werden jetzt beibehalten:

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

Das Ziel dieser Beispiele besteht darin, den Verzeichnispfad (mit Leerzeichen und Anführungszeichen) "C:\Program Files (x86)\Microsoft\" an einen nativen Befehl zu übergeben, sodass er den Pfad als Anführungszeichen erhält.

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 dieselben Ergebnisse im Legacy Modus zu erhalten, müssen Sie die Anführungszeichen mit escapen oder das Token zum Beenden der Analyse 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

Der umgekehrte Schrägstrich (\) wird von PowerShell nicht als Escapezeichen erkannt. Es handelt sich um das Escapezeichen, das von der zugrunde liegenden API für ProcessStartInfo.ArgumentList verwendet wird.

In PowerShell 7.3 besteht nun auch die Möglichkeit zum Nachverfolgen der Parameterbindung für native Befehle. Weitere Informationen finden Sie unter Trace-Command.

Übergeben von Argumenten an PowerShell-Befehle

Ab PowerShell 3.0 können Sie das Token für das Ende der Parameter (--) verwenden, um die Interpretation von Eingaben durch PowerShell als PowerShell-Parameter zu beenden. Dies ist eine Konvention, die in der POSIX Shell and Utilities-Spezifikation angegeben ist.

Das Token für das Ende der Parameter

Das Token für das Ende der Parameter (--) gibt an, dass alle folgenden Argumente in ihrer tatsächlichen Form übergeben werden sollen, als würden doppelte Anführungszeichen um sie herum platziert. Beispielsweise können Sie die Zeichenfolge -InputObject ausgeben--, ohne Anführungszeichen zu verwenden oder sie als Parameter interpretieren zu lassen:

Write-Output -- -InputObject
-InputObject

Im Gegensatz zum Token zum Beenden der Analyse (--%) 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 Tildenzeichen (~) hat in PowerShell eine besondere Bedeutung. Wenn es mit PowerShell-Befehlen am Anfang eines Pfads verwendet wird, wird das Tildenzeichen auf das Basisverzeichnis des Benutzers erweitert. Wenn das Tildenzeichen 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 Name-Parameter eine New-Item Zeichenfolge. Das Tildenzeichen wird als Literalzeichen behandelt. Um in das neu erstellte Verzeichnis zu wechseln, müssen Sie den Pfad mit dem Tildenzeichen 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 Tildenzeichen mit nativen Befehlen verwenden, übergibt PowerShell die Tilde als Literalzeichen. Die Verwendung der Tilde in einem Pfad führt zu Fehlern bei nativen Befehlen unter Windows, die das Tildenzeichen 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

Weitere Informationen