about_Parsing

Kurze Beschreibung

Beschreibt, wie PowerShell Befehle analysiert.

Lange Beschreibung

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

Wenn Sie beispielsweise Folgendes eingeben:

Write-Host book

PowerShell unterteilt den Befehl in zwei Token Write-Host und bookinterpretiert 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, stellt Get- PowerShell dem Befehl als Standardverb vor. PowerShell analysiert Service z. B. 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 durchsucht wird.
  • Externe Programme mit demselben Namen werden zuerst aufgelöst, sodass Sie das beabsichtigte Cmdlet möglicherweise nicht ausführen.
  • Get-Help und Get-Command nicht verblose Namen erkennen.
  • Der Befehlsname kann ein reserviertes Wort oder eine Sprache Schlüsselwort (keyword) sein. Process ist beides und kann nicht aufgelöst Get-Processwerden.

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
  • Zeichenfolgenliterale müssen in Anführungszeichen enthalten sein.
  • Zahlen werden als numerische Werte und nicht als Eine Reihe von Zeichen behandelt (es sei denn, escaped).
  • Operatoren, einschließlich unärer Operatoren wie - und -not binäre Operatoren, +-gtwerden als Operatoren interpretiert und ihre jeweiligen Vorgänge auf ihre Argumente angewendet (Operanden).
  • Attribut- und Konvertierungsausdrücke werden als Ausdrücke analysiert und auf untergeordnete Ausdrücke angewendet. Beispiel: [int] '7'
  • Variable Verweise werden auf ihre Werte ausgewertet, aber splatting ist verboten und verursacht einen Parserfehler.
  • Alles andere wird als befehl behandelt, der aufgerufen werden soll.

Argumentmodus

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. Der Variableverweis kann den Memberzugriff oder die Indizierung umfassen.

    • Zusätzliche Zeichen nach einfachen Variablenbezügen, 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 enthält, wird der erste zusätzliche Zeichen als Beginn eines neuen Arguments betrachtet. Führt z. B $HOME.Length-more . zu zwei Argumenten: dem Wert 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 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 mit einem neuen Ausdruck

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

  • Initial at sign (@) begins expression syntaxes such as splatting (@args), arrays (@(1,2,3)) and hash table literals (@{a=1;b=2}).

  • (), $()und @() am Anfang eines Tokens erstellen Sie 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 angestelltes Literal $() wie eine erweiterbare Zeichenfolge vorangestellt wird, () beginnt 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 Metacharactern, die noch entweichen müssen. Siehe Behandeln von Sonderzeichen.

    • Die Argumentmodus-Metacharacter (Zeichen mit spezieller syntaktischer Bedeutung) sind: <space> ' " ` , ; ( ) { } | & < > @ #. Von diesen sind < > @ # nur zu Beginn eines Tokens besonders.
  • Das Stoppanalysetoken (--%) ändert die Interpretation aller neu Standard ing-Argumente. Weitere Informationen finden Sie im Abschnitt "Stop-Parsing Token" weiter 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 lautet 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 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 von den Ausdrücken zurückgegebenen Werten zugewiesen sind.

Beispiel Mode Ergebnis
Write-Output !1 Argument "!1" (Zeichenfolge)
Write-Output (!1) expression False (boolean)
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)

Verarbeiten von Sonderzeichen

Das Backtick-Zeichen (`) kann verwendet werden, um ein beliebiges Sonderzeichen in einem Ausdruck zu escapen. Dies ist am nützlichsten für das Escapen der Argumentmodus-Metacharacter, die Sie als Literalzeichen und nicht als Metacharacter verwenden möchten. 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. Dies verbessert die Lesbarkeit eines Befehls, der mehrere Parameter mit langen Namen und Argumentwerten verwendet. Zum 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 erkennen und leicht zu vergessen sein.
  • Ein zusätzliches Leerzeichen, nachdem der Backtick die Zeilenfortsetzung unterbrochen hat. Da der Platz schwer zu erkennen ist, kann es schwierig sein, den Fehler zu finden.

PowerShell bietet mehrere Möglichkeiten, Umbruchlinien an natürlichen Punkten in der Syntax zu trennen.

  • Nach Pipezeichen (|)
  • 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. Zum 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 Stoppanalysetoken

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 Stoppanalysetoken ist nur für systemeigene Befehle auf Windows-Plattformen vorgesehen.

Platzieren Sie beim Aufrufen eines systemeigenen Befehls das Stoppanalysetoken vor den Programmargumenten. Diese Technik ist viel einfacher als die Verwendung von Escapezeichen, um Fehlinterpretation zu verhindern.

Wenn ein Stop-Parsing-Token auftritt, behandelt PowerShell die neu Standard Zeichen in der Zeile als Literal. Die einzige Interpretation, die sie ausführt, besteht darin, Werte für Umgebungsvariablen zu ersetzen, die die standardmäßige Windows-Schreibweise 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 Stop-Parsing-Token ist nur wirksam, bis das nächste Neueline- oder Pipelinezeichen vorhanden ist. Sie können das Zeilenfortsetzungszeichen (`) nicht verwenden, um den Effekt zu erweitern oder ein Befehlstrennzeichen (;) zum Beenden des Effekts zu verwenden.

%variable% Außer Umgebungsvariablen-Verweisen können Sie keine anderen dynamischen Elemente in den Befehl einbetten. Das Escapen eines % Zeichens als %%, wie Sie innerhalb von Batchdateien vorgehen können, wird nicht unterstützt. %<name>% Token werden unveränderlich erweitert. Wenn <name> nicht auf eine definierte Umgebungsvariable verwiesen wird, wird das Token wie folgt übergeben.

Sie können die Streamumleitung (z >file.txt. B. ) nicht verwenden, da sie 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.

Übergeben von Argumenten, die Anführungszeichen enthalten

Einige systemeigene 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.

Achtung

Das neue Verhalten ist eine bahnbrechende Änderung des Windows PowerShell 5.1-Verhaltens. 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 <>
    

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 anführungszeichenierte Zeichenfolge 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 Legacy Modus zu erhalten, müssen Sie die Anführungszeichen escapen 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

Der umgekehrte Schrägstrich (\) wird von PowerShell nicht als Escapezeichen erkannt. Es ist 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 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 End-of-Parameters-Token

Das End-of-Parameters-Token (--) gibt an, dass alle darauf folgenden Argumente in ihrer tatsächlichen Form übergeben werden müssen, als ob doppelte Anführungszeichen um sie herum platziert wurden. Sie -- können beispielsweise die Zeichenfolge -InputObject ohne Anführungszeichen ausgeben oder als Parameter interpretiert 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.

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

Weitere Informationen