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
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ń cmdlet lub natywnych plików wykonywalnych. Jeśli nazwa polecenia nie ma dokładnego dopasowania, program PowerShell poprzedza Get-
polecenie jako domyślny czasownik. 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ą rozpoznawane jako pierwsze, 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 , 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ściami w języku skryptowym. Wyrażenia to reprezentacje 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 zostały uniknione).
- Operatory, w tym operatory jednoargumentowe, takie jak
-
+
i-not
-gt
i operatory binarne, są interpretowane jako operatory i stosują odpowiednie operacje na argumentach (operandy). - 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 splatting jest zabroniony 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 będzie 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łowie.
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 rozszerzalny, 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, który można rozwinąć. 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ą uważane za część tego samego argumentu. Dołącz nazwę zmiennej w nawiasach klamrowych ({}
), 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 rozszerzalnego. Początkowe, kolejne lub końcowe przecinki nie są obsługiwane.Nawiasy (
()
) rozpoczynają nowe wyrażenieOperator wyrażenia podrzędnego (
$()
) rozpoczyna wyrażenie osadzonePoczątkowy znak (
@
) 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.- Po kolejnych znakach pierwszy dodatkowy znak jest traktowany jako początek nowego, oddzielnego argumentu.
- Gdy poprzedzony literałem 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 analizowania (
--%
) zmienia interpretację wszystkich pozostałych argumentów. Aby uzyskać więcej informacji, zobacz sekcję tokenu zatrzymania analizowania poniżej.
Przykłady
Poniższa tabela zawiera kilka przykładów tokenów przetworzonych w trybie wyrażenia i trybie argumentu oraz ocenie tych tokenów. W tych przykładach wartość zmiennej $a
to 4
.
Przykład | Tryb | Result |
---|---|---|
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 | Tryb | Result |
---|---|---|
Write-Output !1 |
argument | "!1" (ciąg) |
Write-Output (!1) |
wyrażenie | False (wartość logiczna) |
Write-Output (2) |
wyrażenie | 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 |
wyrażenie | "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 z możliwością rozwinięcia:
"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.
Kontynuacja wiersza
Znak backtick może być również używany na końcu wiersza, aby umożliwić kontynuowanie danych wejściowych w następnym wierszu. Poprawia 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ę linii. Ponieważ miejsce jest trudne do zobaczenia, może być trudne do znalezienia błędu.
Program PowerShell udostępnia kilka sposobów dzielenia 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ć splattingu. 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 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 programu PowerShell.
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F
Token zatrzymania analizowania
Począwszy od programu PowerShell 3.0, możesz użyć tokenu stop-parsing (--%
), aby uniemożliwić programowi PowerShell interpretowanie danych wejściowych jako poleceń lub wyrażeń programu PowerShell.
Uwaga
Token zatrzymania analizowania 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 korzystających ze standardowej notacji systemu Windows, takiej jak %USERPROFILE%
.
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F
Program PowerShell wysyła następujący ciąg polecenia do icacls.exe
programu:
X:\VMS /grant Dom\HVAdmin:(CI)(OI)F
Token zatrzymania analizowania jest skuteczny tylko do momentu 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 przerwać 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 przykład >file.txt
), ponieważ są one przekazywane 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 wystąpienie błędu.
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 zatrzymania analizowania nie jest wymagany podczas 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 natywne polecenia oczekują argumentów zawierających znaki cudzysłowu. Program PowerShell 7.3 zmienił sposób analizowania wiersza polecenia dla poleceń natywnych.
Uwaga
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 stop-parsing () lub Start-Process
polecenia cmdlet,--%
aby uniknąć natywnego przekazywania argumentów 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 ustawienie domyślne 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 argumentu 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
z poziomu 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 (ze 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 użyć cudzysłowów lub użyć tokenu zatrzymania analizowania (--%
):
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 programu 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.
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 i narzędzi POSIX.
Token końca parametrów
Token końca parametrów (--
) wskazuje, że wszystkie następujące argumenty mają zostać przekazane w ich rzeczywistej formie, tak jakby cudzysłowy zostały umieszczone wokół nich. Na przykład za pomocą --
polecenia można wyświetlić ciąg -InputObject
bez użycia cudzysłowów lub interpretować go jako parametr:
Write-Output -- -InputObject
-InputObject
W przeciwieństwie do tokenu stop-parsing (--%
), wszystkie wartości po tokenie --
mogą być interpretowane jako wyrażenia przez program 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
elementu .
Arg 0 is <-a>
Arg 1 is <-b>
Arg 2 is <-->
Arg 3 is <-c>
Tylda (~)
Znak tyldy (~
) ma specjalne znaczenie w programie PowerShell. Gdy jest 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 Name oczekiwanego New-Item
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\~
Gdy używasz znaku tyldy z natywnymi poleceniami, program PowerShell przekazuje tyldę 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