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-Host bookinterpretuje 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 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 , 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ś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 -gti 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ł -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 rozszerzalnego. Początkowe, kolejne lub końcowe przecinki nie są obsługiwane.

  • Nawiasy (()) rozpoczynają nowe wyrażenie

  • Operator wyrażenia podrzędnego ($()) rozpoczyna wyrażenie osadzone

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

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

Zobacz też