Udostępnij za pośrednictwem


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-Hostbook, 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 i Get-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ć jako Get-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 -+-gti -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ł -moreciągu .
  • Znaki cudzysłowu (' i ") rozpoczynają ciągi

  • Nawiasy klamrowe ({}) rozpoczynają nowe bloki skryptów

  • Przecinki (,) 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żenie

  • Operator podwyrażu ($()) rozpoczyna wyrażenie osadzone

  • Począ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.
  • 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 (+, -, -eqitp.)
  • 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.txtprzykł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, Standardi 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-ItemName 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

Zobacz też