about_Parsing
Krótki opis
Opisuje sposób analizowania poleceń programu PowerShell.
Długi opis
Po wprowadzeniu polecenia w wierszu polecenia program PowerShell dzieli tekst polecenia na serię segmentów nazywanych tokenami , a następnie określa, jak interpretować każdy token.
Jeśli na przykład wpiszesz:
Write-Host book
Program PowerShell dzieli polecenie na dwa tokeny i Write-Host
book
, i interpretuje każdy token niezależnie przy użyciu jednego z dwóch głównych trybów analizowania: trybu wyrażenia i trybu argumentu.
Uwaga
Gdy program PowerShell analizuje dane wejściowe polecenia, próbuje rozpoznać nazwy poleceń dla poleceń cmdlet lub natywnych plików wykonywalnych. Jeśli nazwa polecenia nie ma dokładnego dopasowania, program PowerShell poprzedza Get-
polecenie jako domyślne zlecenie. Na przykład program PowerShell analizuje Service
jako Get-Service
. Nie zaleca się używania tej funkcji z następujących powodów:
- To nieefektywne. Powoduje to wielokrotne wyszukiwanie w programie PowerShell.
- Programy zewnętrzne o tej samej nazwie są najpierw rozpoznawane, więc nie można wykonać zamierzonego polecenia cmdlet.
Get-Help
iGet-Command
nie rozpoznaje nazw bez czasowników.- Nazwa polecenia może być słowem zastrzeżonym lub słowem kluczowym języka.
Process
jest zarówno parametrem , jak i nie można go rozpoznać jakoGet-Process
.
Tryb wyrażeń
Tryb wyrażeń jest przeznaczony do łączenia wyrażeń wymaganych do manipulowania wartością w języku skryptowym. Wyrażenia są reprezentacjami wartości w składni programu PowerShell i mogą być proste lub złożone, na przykład:
Wyrażenia literału są bezpośrednimi reprezentacjami ich wartości:
'hello'
32
Wyrażenia zmiennych przenoszą wartość zmiennej, do której się odwołują:
$x
$script:path
Operatory łączą inne wyrażenia do oceny:
-12
-not $Quiet
3 + 7
$input.Length -gt 1
- Literały ciągu znaków muszą być zawarte w cudzysłowie.
- Liczby są traktowane jako wartości liczbowe, a nie jako seria znaków (chyba że uniknie).
- Operatory, w tym operatory jednoargumentowe, takie jak
-
+
-gt
i-not
i operatory binarne, są interpretowane jako operatory i stosują odpowiednie operacje na argumentach (operandach). - Wyrażenia atrybutów i konwersji są analizowane jako wyrażenia i stosowane do wyrażeń podrzędnych. Na przykład:
[int] '7'
. - Odwołania do zmiennych są oceniane na ich wartości, ale zaplatanie jest zabronione i powoduje błąd analizatora.
- Wszystkie inne elementy są traktowane jako polecenie do wywołania.
Tryb argumentu
Podczas analizowania program PowerShell najpierw analizuje dane wejściowe jako wyrażenie. Jednak po napotkaniu wywołania polecenia analizowanie jest kontynuowane w trybie argumentu. Jeśli masz argumenty zawierające spacje, takie jak ścieżki, należy ująć te wartości argumentów w cudzysłów.
Tryb argumentów jest przeznaczony do analizowania argumentów i parametrów dla poleceń w środowisku powłoki. Wszystkie dane wejściowe są traktowane jako ciąg rozwijalny, chyba że używa jednej z następujących składni:
Znak dolara (
$
), po którym następuje nazwa zmiennej, rozpoczyna odwołanie do zmiennej. W przeciwnym razie jest interpretowany jako część ciągu rozszerzalnego. Odwołanie do zmiennej może obejmować dostęp do składowych lub indeksowanie.- Dodatkowe znaki po prostych odwołaniach do zmiennych, takich jak
$HOME
, są traktowane jako część tego samego argumentu. Należy ująć nazwę zmiennej w nawiasy klamrowe ({}
), aby oddzielić ją od kolejnych znaków. Na przykład${HOME}
. - Gdy odwołanie do zmiennej zawiera dostęp do składowych, pierwszy z dodatkowych znaków jest traktowany jako początek nowego argumentu. Na przykład
$HOME.Length-more
wyniki w dwóch argumentach: wartość$HOME.Length
i literał-more
ciągu .
- Dodatkowe znaki po prostych odwołaniach do zmiennych, takich jak
Znaki cudzysłowu (
'
i"
) rozpoczynają ciągiNawiasy klamrowe (
{}
) rozpoczynają nowe bloki skryptówPrzecinki (
,
) wprowadzają listy przekazywane jako tablice, chyba że wywoływane polecenie jest aplikacją natywną, w tym przypadku są interpretowane jako część ciągu z możliwością rozszerzania. Początkowe, kolejne lub końcowe przecinki nie są obsługiwane.Nawiasy (
()
) rozpoczynają nowe wyrażenieOperator podwyrażu (
$()
) rozpoczyna wyrażenie osadzonePoczątkowy przy znaku (
@
) rozpoczyna składnie wyrażeń, takie jak splatting (@args
), tablice (@(1,2,3)
) i literały tabeli skrótu (@{a=1;b=2}
).()
,$()
i@()
na początku tokenu utwórz nowy kontekst analizowania, który może zawierać wyrażenia lub zagnieżdżone polecenia.- Gdy następuje kolejne znaki, pierwszy dodatkowy znak jest uznawany za początek nowego, oddzielnego argumentu.
- Gdy poprzedzany przez literał
$()
bez cudzysłowu działa jak ciąg rozwijalny,()
uruchamia nowy argument, który jest wyrażeniem i@()
jest traktowany jako literał@
rozpoczynający()
nowy argument, który jest wyrażeniem.
Wszystkie inne elementy są traktowane jako ciąg rozszerzalny, z wyjątkiem metacharacters, które nadal wymagają ucieczki. Zobacz Obsługa znaków specjalnych.
- Metacharactery trybu argumentu (znaki ze specjalnym znaczeniem składniowym) to:
<space> ' " ` , ; ( ) { } | & < > @ #
. Z nich< > @ #
są specjalne tylko na początku tokenu.
- Metacharactery trybu argumentu (znaki ze specjalnym znaczeniem składniowym) to:
Token zatrzymania analizy (
--%
) zmienia interpretację wszystkich pozostałych argumentów. Aby uzyskać więcej informacji, zobacz sekcję tokenu zatrzymywania analizowania poniżej.
Przykłady
W poniższej tabeli przedstawiono kilka przykładów tokenów przetworzonych w trybie wyrażeń i trybie argumentów oraz ocenę tych tokenów. W tych przykładach wartość zmiennej $a
to 4
.
Przykład | Mode | Wynik |
---|---|---|
2 |
Wyrażenie | 2 (liczba całkowita) |
`2 |
Wyrażenie | "2" (polecenie) |
Write-Output 2 |
Wyrażenie | 2 (liczba całkowita) |
2+2 |
Wyrażenie | 4 (liczba całkowita) |
Write-Output 2+2 |
Argument | "2+2" (ciąg) |
Write-Output(2+2) |
Wyrażenie | 4 (liczba całkowita) |
$a |
Wyrażenie | 4 (liczba całkowita) |
Write-Output $a |
Wyrażenie | 4 (liczba całkowita) |
$a+2 |
Wyrażenie | 6 (liczba całkowita) |
Write-Output $a+2 |
Argument | "4+2" (ciąg) |
$- |
Argument | "$-" (polecenie) |
Write-Output $- |
Argument | "$-" (ciąg) |
a$a |
Wyrażenie | "a$a" (polecenie) |
Write-Output a$a |
Argument | "a4" (ciąg) |
a'$a' |
Wyrażenie | "a$a" (polecenie) |
Write-Output a'$a' |
Argument | "a$a" (ciąg) |
a"$a" |
Wyrażenie | "a$a" (polecenie) |
Write-Output a"$a" |
Argument | "a4" (ciąg) |
a$(2) |
Wyrażenie | "a$(2)" (polecenie) |
Write-Output a$(2) |
Argument | "a2" (ciąg) |
Każdy token może być interpretowany jako jakiś typ obiektu, taki jak wartość logiczna lub ciąg. Program PowerShell próbuje określić typ obiektu z wyrażenia. Typ obiektu zależy od typu parametru oczekiwanego przez polecenie i od tego, czy program PowerShell wie, jak przekonwertować argument na poprawny typ. W poniższej tabeli przedstawiono kilka przykładów typów przypisanych do wartości zwracanych przez wyrażenia.
Przykład | Mode | Wynik |
---|---|---|
Write-Output !1 |
Argument | "!1" (ciąg) |
Write-Output (!1) |
expression | False (wartość logiczna) |
Write-Output (2) |
expression | 2 (liczba całkowita) |
Set-Variable AB A,B |
Argument | "A", "B" (tablica) |
CMD /CECHO A,B |
Argument | "A,B" (ciąg) |
CMD /CECHO $AB |
expression | "A B" (tablica) |
CMD /CECHO :$AB |
Argument | ':A B' (ciąg) |
Obsługa znaków specjalnych
Znak backtick (`
) może służyć do ucieczki od dowolnego znaku specjalnego w wyrażeniu. Jest to najbardziej przydatne w przypadku ucieczki metacharacters trybu argumentów, których chcesz użyć jako znaków literałów, a nie jako metatypu. Aby na przykład użyć znaku dolara ($
) jako literału w ciągu, który można rozwinąć:
"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.
Kontynuacja wiersza
Znak backtick można również użyć na końcu wiersza, aby umożliwić kontynuowanie danych wejściowych w następnym wierszu. Zwiększa to czytelność polecenia, które przyjmuje kilka parametrów z długimi nazwami i wartościami argumentów. Na przykład:
New-AzVm `
-ResourceGroupName "myResourceGroupVM" `
-Name "myVM" `
-Location "EastUS" `
-VirtualNetworkName "myVnet" `
-SubnetName "mySubnet" `
-SecurityGroupName "myNetworkSecurityGroup" `
-PublicIpAddressName "myPublicIpAddress" `
-Credential $cred
Należy jednak unikać używania kontynuacji wiersza.
- Znaki backtick mogą być trudne do zobaczenia i łatwe do zapomnienia.
- Dodatkowe miejsce po backtick przerywa kontynuację wiersza. Ponieważ miejsce jest trudne do zobaczenia, może być trudne do znalezienia błędu.
Program PowerShell udostępnia kilka sposobów podziału wierszy w naturalnych punktach składni.
- Po znakach potoku (
|
) - Po operatorach binarnych (
+
,-
,-eq
itp.) - Po przecinkach (
,
) w tablicy - Po otwarciu znaków, takich jak
[
, ,{
(
W przypadku dużego zestawu parametrów należy zamiast tego użyć narzędzia splatting. Na przykład:
$parameters = @{
ResourceGroupName = "myResourceGroupVM"
Name = "myVM"
Location = "EastUS"
VirtualNetworkName = "myVnet"
SubnetName = "mySubnet"
SecurityGroupName = "myNetworkSecurityGroup"
PublicIpAddressName = "myPublicIpAddress"
Credential = $cred
}
New-AzVm @parameters
Przekazywanie argumentów do poleceń natywnych
Podczas uruchamiania poleceń natywnych z poziomu programu PowerShell argumenty są najpierw analizowane przez program PowerShell. Przeanalizowane argumenty są następnie łączone w jeden ciąg z każdym parametrem oddzielonym spacją.
Na przykład następujące polecenie wywołuje icacls.exe
program.
icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F
Aby uruchomić to polecenie w programie PowerShell 2.0, należy użyć znaków ucieczki, aby zapobiec błędnej interpretacji nawiasów w programie PowerShell.
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F
Token zatrzymania analizy
Począwszy od programu PowerShell 3.0, można użyć tokenu stop-parsing (--%
), aby uniemożliwić programowi PowerShell interpretowanie danych wejściowych jako poleceń lub wyrażeń programu PowerShell.
Uwaga
Token zatrzymania analizy jest przeznaczony tylko do używania natywnych poleceń na platformach Windows.
Podczas wywoływania natywnego polecenia umieść token stop-parsing przed argumentami programu. Ta technika jest znacznie łatwiejsza niż używanie znaków ucieczki, aby zapobiec błędnej interpretacji.
W przypadku napotkania tokenu zatrzymania analizowania program PowerShell traktuje pozostałe znaki w wierszu jako literał. Jedyną interpretacją, którą wykonuje, jest zastąpienie wartości zmiennych środowiskowych, które używają standardowej notacji systemu Windows, takiej jak %USERPROFILE%
.
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F
Program PowerShell wysyła do programu następujący ciąg icacls.exe
polecenia:
X:\VMS /grant Dom\HVAdmin:(CI)(OI)F
Token zatrzymania analizy jest skuteczny tylko do następnego nowego wiersza lub znaku potoku. Nie można użyć znaku kontynuacji wiersza (`
), aby rozszerzyć jego efekt lub użyć ogranicznika polecenia (;
), aby zakończyć jego efekt.
%variable%
Poza odwołaniami do zmiennych środowiskowych nie można osadzić żadnych innych elementów dynamicznych w poleceniu . Ucieczka znaku jako %%
, sposób, w jaki można wykonać wewnątrz plików wsadowych%
, nie jest obsługiwana. %<name>%
tokeny są niezmiennie rozwinięte. Jeśli <name>
nie odwołuje się do zdefiniowanej zmiennej środowiskowej, token jest przekazywany zgodnie z rzeczywistym użyciem.
Nie można użyć przekierowania strumienia (na >file.txt
przykład ), ponieważ są przekazywane dosłownie jako argumenty do polecenia docelowego.
W poniższym przykładzie pierwszy krok uruchamia polecenie bez użycia tokenu zatrzymania analizowania. Program PowerShell oblicza cytowany ciąg i przekazuje wartość (bez cudzysłowów) do cmd.exe
, co powoduje błąd.
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"
Uwaga
Token zatrzymywania analizy nie jest wymagany w przypadku korzystania z poleceń cmdlet programu PowerShell. Jednak przydatne może być przekazanie argumentów do funkcji programu PowerShell, która została zaprojektowana w celu wywołania natywnego polecenia z tymi argumentami.
Przekazywanie argumentów zawierających znaki cudzysłowu
Niektóre polecenia natywne oczekują argumentów zawierających znaki cudzysłowu. Program PowerShell 7.3 zmienił sposób analizowania wiersza polecenia dla poleceń natywnych.
Przestroga
Nowe zachowanie to zmiana powodująca niezgodność z zachowaniem programu Windows PowerShell 5.1. Może to spowodować przerwanie skryptów i automatyzacji, które działają wokół różnych problemów podczas wywoływania aplikacji natywnych. Użyj tokenu zatrzymania analizowania () lub Start-Process
polecenia cmdlet,--%
aby uniknąć przekazywania argumentów natywnych w razie potrzeby.
Nowa $PSNativeCommandArgumentPassing
zmienna preferencji kontroluje to zachowanie. Ta zmienna umożliwia wybranie zachowania w czasie wykonywania. Prawidłowe wartości to Legacy
, Standard
i Windows
. Domyślne zachowanie jest specyficzne dla platformy. Na platformach Windows domyślne ustawienie to Windows
i platformy inne niż Windows mają wartość domyślną Standard
.
Legacy
jest zachowaniem historycznym. Zachowanie Windows
trybu i Standard
jest takie samo, z wyjątkiem, w Windows
trybie, wywołania następujących plików automatycznie używają przekazywania argumentów Legacy
stylu.
cmd.exe
cscript.exe
wscript.exe
- kończące się na
.bat
- kończące się na
.cmd
- kończące się na
.js
- kończące się na
.vbs
- kończące się na
.wsf
$PSNativeCommandArgumentPassing
Jeśli parametr jest ustawiony na Legacy
wartość lub Standard
, analizator nie sprawdza tych plików.
Uwaga
W poniższych przykładach użyto TestExe.exe
narzędzia . Możesz utworzyć TestExe
na podstawie kodu źródłowego. Zobacz TestExe w repozytorium źródłowym programu PowerShell.
Nowe zachowania udostępniane przez tę zmianę:
Ciągi literału lub ciągi rozszerzalne z osadzonymi cudzysłowami są teraz zachowywane:
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>
Puste ciągi jako argumenty są teraz zachowywane:
PS> TestExe -echoargs '' a b '' Arg 0 is <> Arg 1 is <a> Arg 2 is <b> Arg 3 is <>
Celem tych przykładów jest przekazanie ścieżki katalogu (z spacjami i cudzysłowami) "C:\Program Files (x86)\Microsoft\"
do natywnego polecenia, tak aby otrzymał ścieżkę jako ciąg cytowany.
W Windows
trybie lub Standard
w poniższych przykładach przedstawiono oczekiwane wyniki:
TestExe -echoargs """${env:ProgramFiles(x86)}\Microsoft\"""
TestExe -echoargs '"C:\Program Files (x86)\Microsoft\"'
Aby uzyskać te same wyniki w Legacy
trybie, należy uciec od cudzysłowów lub użyć tokenu stop-parsing (--%
):
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\\""
Uwaga
Znak ukośnika odwrotnego (\
) nie jest rozpoznawany jako znak ucieczki przez program PowerShell. Jest to znak ucieczki używany przez podstawowy interfejs API dla elementu ProcessStartInfo.ArgumentList.
Program PowerShell 7.3 dodał również możliwość śledzenia powiązania parametrów dla poleceń natywnych. Aby uzyskać więcej informacji, zobacz Trace-Command(Polecenie śledzenia).
Przekazywanie argumentów do poleceń programu PowerShell
Począwszy od programu PowerShell 3.0, możesz użyć tokenu końca parametrów (--
), aby uniemożliwić programowi PowerShell interpretowanie danych wejściowych jako parametrów programu PowerShell. Jest to konwencja określona w specyfikacji powłoki POSIX i narzędzi.
Token końca parametrów
Token końca parametrów (--
) wskazuje, że wszystkie argumenty po nim mają zostać przekazane w rzeczywistej formie, tak jakby wokół nich umieszczono podwójne cudzysłowy. Na przykład za pomocą --
ciągu można wyświetlić ciąg -InputObject
bez użycia cudzysłowów lub interpretowania go jako parametru:
Write-Output -- -InputObject
-InputObject
W przeciwieństwie do tokenu stop-parsing (--%
), wszystkie wartości po --
tokenie można interpretować jako wyrażenia za pomocą programu PowerShell.
Write-Output -- -InputObject $env:PROCESSOR_ARCHITECTURE
-InputObject
AMD64
To zachowanie dotyczy tylko poleceń programu PowerShell. Jeśli używasz tokenu --
podczas wywoływania polecenia zewnętrznego, --
ciąg jest przekazywany jako argument do tego polecenia.
TestExe -echoargs -a -b -- -c
Dane wyjściowe pokazują, że --
jest przekazywany jako argument do TestExe
.
Arg 0 is <-a>
Arg 1 is <-b>
Arg 2 is <-->
Arg 3 is <-c>
Tilde (~)
Znak tyldy (~
) ma specjalne znaczenie w programie PowerShell. Gdy jest on używany z poleceniami programu PowerShell na początku ścieżki, znak tyldy jest rozszerzany do katalogu macierzystego użytkownika. Jeśli znak tyldy jest używany gdziekolwiek indziej w ścieżce, jest traktowany jako znak literału.
PS D:\temp> $PWD
Path
----
D:\temp
PS D:\temp> Set-Location ~
PS C:\Users\user2> $PWD
Path
----
C:\Users\user2
W tym przykładzie parametr New-Item
Name oczekiwanego ciągu. Znak tyldy jest traktowany jako znak literału. Aby przejść do nowo utworzonego katalogu, musisz zakwalifikować ścieżkę znakiem tyldy.
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\~
W przypadku używania znaku tyldy z poleceniami natywnymi program PowerShell przekazuje tilde jako znak literału. Użycie tyldy w ścieżce powoduje błędy dla natywnych poleceń w systemie Windows, które nie obsługują znaku tyldy.
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