Compartilhar via


about_Parsing

Descrição breve

Descreve como o PowerShell analisa comandos.

Descrição longa

Quando você insere um comando no prompt de comando, o PowerShell divide o texto do comando em uma série de segmentos chamados tokens e determina como interpretar cada token.

Por exemplo, se você digitar:

Write-Host book

O PowerShell divide o comando em dois tokens Write-Host e bookinterpreta cada token de forma independente usando um dos dois principais modos de análise: modo de expressão e modo de argumento.

Observação

À medida que o PowerShell analisa a entrada de comando, ele tenta resolver os nomes de comando para cmdlets ou executáveis nativos. Se um nome de comando não tiver uma correspondência exata, o PowerShell precederá Get- o comando como um verbo padrão. Por exemplo, o PowerShell analisa Service como Get-Service. Não é recomendável usar esse recurso pelos seguintes motivos:

  • É ineficiente. Isso faz com que o PowerShell pesquise várias vezes.
  • Programas externos com o mesmo nome são resolvidos primeiro, portanto, você não pode executar o cmdlet pretendido.
  • Get-Help e Get-Command não reconheça nomes sem verbos.
  • O nome do comando pode ser uma palavra reservada ou uma palavra-chave de idioma. Process é ambos, e não pode ser resolvido para Get-Process.

Modo de expressão

O modo de expressão destina-se à combinação de expressões, necessárias para manipulação de valor em uma linguagem de script. As expressões são representações de valores na sintaxe do PowerShell e podem ser simples ou compostas, por exemplo:

As expressões literais são representações diretas de seus valores:

'hello'
32

As expressões de variável carregam o valor da variável a que fazem referência:

$x
$script:path

Os operadores combinam outras expressões para avaliação:

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • Os literais de cadeia de caracteres devem estar contidos entre aspas.
  • Os números são tratados como valores numéricos e não como uma série de caracteres (a menos que escape).
  • Operadores, incluindo operadores unários como - e -not e operadores binários como + e -gt, são interpretados como operadores e aplicam suas respectivas operações em seus argumentos (operandos).
  • As expressões de atributo e conversão são analisadas como expressões e aplicadas a expressões subordinadas. Por exemplo: [int] '7'.
  • As referências de variáveis são avaliadas de acordo com seus valores, mas o splatting é proibido e causa um erro do analisador.
  • Qualquer outra coisa é tratada como um comando a ser invocado.

Modo de argumento

Ao analisar, o PowerShell primeiro procura interpretar a entrada como uma expressão. Mas quando uma invocação de comando é encontrada, a análise continua no modo de argumento. Se você tiver argumentos que contenham espaços, como caminhos, deverá colocar esses valores de argumento entre aspas.

O modo de argumento foi projetado para analisar argumentos e parâmetros para comandos em um ambiente de shell. Todas as entradas são tratadas como uma cadeia de caracteres expansível, a menos que usem uma das seguintes sintaxes:

  • O cifrão ($) seguido por um nome de variável inicia uma referência de variável, caso contrário, é interpretado como parte da cadeia de caracteres expansível. A referência de variável pode incluir acesso ou indexação de membros.

    • Caracteres adicionais após referências de variáveis simples, como $HOME, são considerados parte do mesmo argumento. Coloque o nome da variável entre chaves ({}) para separá-lo dos caracteres subsequentes. Por exemplo, ${HOME}.
    • Quando a referência de variável inclui acesso de membro, o primeiro de quaisquer caracteres adicionais é considerado o início de um novo argumento. Por exemplo$HOME.Length-more, resulta em dois argumentos: o valor de e o literal -morede cadeia de $HOME.Length caracteres .
  • As aspas (' e ") começam as cadeias de caracteres

  • Chaves ({}) começam um novo script blocos

  • Vírgulas (,) introduzem listas passadas como matrizes, a menos que o comando que está sendo chamado seja um aplicativo nativo, caso em que elas são interpretadas como parte da string expansível. Não há suporte para vírgulas iniciais, consecutivas ou à direita.

  • Parênteses (()) iniciam uma nova expressão

  • O operador de subexpressão ($()) inicia uma expressão incorporada

  • A inicial do sinal de arroba (@) inicia sintaxes de expressão, como splatting (@args), arrays (@(1,2,3)) e literais de tabela de hash (@{a=1;b=2}).

  • (), e@(), no início de um token, $()criar um novo contexto de análise que pode conter expressões ou comandos aninhados.

    • Quando seguido por caracteres adicionais, o primeiro caractere adicional é considerado o início de um argumento novo e separado.
    • Quando precedido por um literal $() sem aspas funciona como uma cadeia de caracteres expansível, () inicia um novo argumento que é uma expressão e @() é considerado literal @ com () o início de um novo argumento que é uma expressão.
  • Todo o resto é tratado como uma cadeia de caracteres expansível, exceto metacaracteres que ainda precisam ser escapados. Consulte Manipulando caracteres especiais.

    • Os metacaracteres do modo de argumento (caracteres com significado sintático especial) são: <space> ' " ` , ; ( ) { } | & < > @ #. Destes, < > @ # são especiais apenas no início de um token.
  • O token de análise de parada (--%) altera a interpretação de todos os argumentos restantes. Para obter mais informações, consulte a seção stop-parsing token abaixo.

Exemplos

A tabela a seguir fornece vários exemplos de tokens processados no modo de expressão e no modo de argumento e a avaliação desses tokens. Para esses exemplos, o valor da variável $a é 4.

Exemplo Mode Result
2 Expression 2 (inteiro)
`2 Expression "2" (comando)
Write-Output 2 Expression 2 (inteiro)
2+2 Expression 4 (inteiro)
Write-Output 2+2 Argumento "2+2" (string)
Write-Output(2+2) Expression 4 (inteiro)
$a Expression 4 (inteiro)
Write-Output $a Expression 4 (inteiro)
$a+2 Expression 6 (inteiro)
Write-Output $a+2 Argumento "4+2" (string)
$- Argumento "$-" (comando)
Write-Output $- Argumento "$-" (cadeia de caracteres)
a$a Expression "a$a" (comando)
Write-Output a$a Argumento "a4" (cadeia de caracteres)
a'$a' Expression "a$a" (comando)
Write-Output a'$a' Argumento "a$a" (cadeia de caracteres)
a"$a" Expression "a$a" (comando)
Write-Output a"$a" Argumento "a4" (cadeia de caracteres)
a$(2) Expression "a$(2)" (comando)
Write-Output a$(2) Argumento "a2" (cadeia de caracteres)

Cada token pode ser interpretado como algum tipo de objeto, como Boolean ou String. O PowerShell tenta determinar o tipo de objeto da expressão. O tipo de objeto depende do tipo de parâmetro que um comando espera e se o PowerShell sabe como converter o argumento para o tipo correto. A tabela a seguir mostra vários exemplos dos tipos atribuídos aos valores retornados pelas expressões.

Exemplo Mode Resultado
Write-Output !1 argument "!1" (cadeia de caracteres)
Write-Output (!1) expressão Falso (booleano)
Write-Output (2) expressão 2 (inteiro)
Set-Variable AB A,B argument 'A','B' (matriz)
CMD /CECHO A,B argument 'A,B' (cadeia de caracteres)
CMD /CECHO $AB expressão 'A B' (matriz)
CMD /CECHO :$AB argument ':A B' (cadeia de caracteres)

Caracteres especiais de manipulação

O caractere de acento grave (`) pode ser usado para escapar de qualquer caractere especial em uma expressão. Isso é mais útil para escapar dos metacaracteres do modo de argumento que você deseja usar como caracteres literais em vez de metacaracteres. Por exemplo, para usar o cifrão ($) como um literal em uma cadeia de caracteres expansível:

"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.

Continuação de linha

O caractere de acento grave também pode ser usado no final de uma linha para permitir que você continue a entrada na próxima linha. Isso é melhorar a legibilidade de um comando que usa vários parâmetros com nomes longos e valores de argumento. Por exemplo:

New-AzVm `
    -ResourceGroupName "myResourceGroupVM" `
    -Name "myVM" `
    -Location "EastUS" `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -Credential $cred

No entanto, você deve evitar usar a continuação de linha.

  • Os caracteres de acento grave podem ser difíceis de ver e fáceis de esquecer.
  • Um espaço extra após o acento grave quebra a continuação da linha. Como o espaço é difícil de ver, pode ser difícil encontrar o erro.

O PowerShell fornece várias maneiras de quebrar linhas em pontos naturais na sintaxe.

  • Após caracteres de barra vertical (|)
  • Depois que os operadores binários (+, -, -eq, etc.)
  • Depois de vírgulas (,) em uma matriz
  • Depois de abrir caracteres como [, {, (

Para um conjunto de parâmetros grande, use splatting. Por exemplo:

$parameters = @{
    ResourceGroupName = "myResourceGroupVM"
    Name = "myVM"
    Location = "EastUS"
    VirtualNetworkName = "myVnet"
    SubnetName = "mySubnet"
    SecurityGroupName = "myNetworkSecurityGroup"
    PublicIpAddressName = "myPublicIpAddress"
    Credential = $cred
}
New-AzVm @parameters

Como passar argumentos para comandos nativos

Ao executar comandos nativos do PowerShell, os argumentos são analisados primeiro pelo PowerShell. Os argumentos analisados são então unidos em uma única cadeia de caracteres com cada parâmetro separado por um espaço.

Por exemplo, o comando a seguir chama o icacls.exe programa.

icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

Para executar esse comando no PowerShell 2.0, você deve usar caracteres de escape para impedir que o PowerShell interprete incorretamente os parênteses.

icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F

O token de análise de parada

A partir do PowerShell 3.0, você pode usar o token stop-parsing (--%) para impedir que o PowerShell interprete a entrada como comandos ou expressões do PowerShell.

Observação

O token de parada de análise destina-se apenas ao uso de comandos nativos em plataformas Windows.

Ao chamar um comando nativo, coloque o token de análise de parada antes dos argumentos do programa. Essa técnica é muito mais fácil do que usar caracteres de escape para evitar interpretações errôneas.

Quando encontra um token de parada de análise, o PowerShell trata os caracteres restantes na linha como um literal. A única interpretação que ele executa é substituir valores por variáveis de ambiente que usam notação padrão do Windows, como %USERPROFILE%.

icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F

O PowerShell envia a seguinte cadeia de caracteres de comando para o icacls.exe programa:

X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

O token de parada de análise é efetivo somente até a próxima nova linha ou caractere de pipeline. Você não pode usar o caractere de continuação de linha (`) para estender seu efeito ou usar um delimitador de comando (;) para encerrar seu efeito.

Além das %variable% referências de variáveis de ambiente, você não pode incorporar nenhum outro elemento dinâmico no comando. Não há suporte para o escape de um % caractere como %%, da maneira que você pode fazer dentro de arquivos em lote. %<name>% tokens são invariavelmente expandidos. Se <name> não se referir a uma variável de ambiente definida, o token será passado no estado em que se encontra.

Você não pode usar o redirecionamento de fluxo (como >file.txt) porque eles são passados literalmente como argumentos para o comando target.

No exemplo a seguir, a primeira etapa executa um comando sem usar o token stop-parsing. O PowerShell avalia a cadeia de caracteres entre aspas e passa o valor (sem aspas) para , o cmd.exeque resulta em um erro.

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"

Observação

O token de parada de análise não é necessário ao usar cmdlets do PowerShell. No entanto, pode ser útil passar argumentos para uma função do PowerShell projetada para chamar um comando nativo com esses argumentos.

Passando argumentos que contêm caracteres de aspas

Alguns comandos nativos esperam argumentos que contenham caracteres de aspas. O PowerShell 7.3 alterou a maneira como a linha de comando é analisada para comandos nativos.

Cuidado

O novo comportamento é uma alteração significativa do comportamento do Windows PowerShell 5.1. Isso pode interromper scripts e automação que solucionam os diversos problemas que ocorrem ao invocar aplicativos nativos. Use o token de análise de parada (--%) ou o Start-Process cmdlet para evitar que o argumento nativo seja passado quando necessário.

A nova $PSNativeCommandArgumentPassing variável de preferência controla esse comportamento. Essa variável permite que você selecione o comportamento em runtime. Os valores válidos são Legacy, Standard e Windows. O comportamento padrão é específico da plataforma. Em plataformas Windows, a configuração padrão é Windows e em plataformas não Windows a configuração padrão é Standard.

Legacy é o comportamento histórico. O comportamento dos modos Windows e Standard são os mesmos, exceto que, no modo Windows, as invocações dos arquivos a seguir usam automaticamente a passagem do argumento de estilo Legacy.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • terminando com .bat
  • terminando com .cmd
  • terminando com .js
  • terminando com .vbs
  • terminando com .wsf

Se o $PSNativeCommandArgumentPassing estiver definido como Legacy ou Standard, o analisador não verificará esses arquivos.

Observação

Os exemplo a seguir usam a ferramenta TestExe.exe. Você pode criar TestExe com base no código-fonte. Confira TestExe no repositório de origem do PowerShell.

Novos comportamentos disponibilizados por essa alteração:

  • Cadeias de caracteres literais ou expansíveis com aspas inseridas. As aspas agora são preservadas:

    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>
    
  • Cadeias de caracteres vazias usadas como argumentos agora são preservadas:

    PS> TestExe -echoargs '' a b ''
    Arg 0 is <>
    Arg 1 is <a>
    Arg 2 is <b>
    Arg 3 is <>
    

O objetivo desses exemplos é passar o caminho do diretório (com espaços e aspas) "C:\Program Files (x86)\Microsoft\" para um comando nativo para que ele receba o caminho como uma string entre aspas.

No Windows modo ou Standard , os exemplos a seguir produzem os resultados esperados:

TestExe -echoargs """${env:ProgramFiles(x86)}\Microsoft\"""
TestExe -echoargs '"C:\Program Files (x86)\Microsoft\"'

Para obter os mesmos resultados no Legacy modo, você deve escapar das aspas ou usar o token 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\\""

Observação

O caractere de barra invertida (\) não é reconhecido como um caractere de escape pelo PowerShell. É o caractere de escape usado pela API subjacente para ProcessStartInfo.ArgumentList.

O PowerShell 7.3 também adicionou a capacidade de rastrear a associação de parâmetros para comandos nativos. Para obter mais informações, confira Trace-Command.

Passando argumentos para comandos do PowerShell

A partir do PowerShell 3.0, você pode usar o token de fim de parâmetros (--) para impedir que o PowerShell interprete a entrada como parâmetros do PowerShell. Essa é uma convenção especificada na especificação POSIX Shell and Utilities.

O token de fim de parâmetros

O token de fim de parâmetros (--) indica que todos os argumentos que o seguem devem ser passados em sua forma real, como se aspas duplas fossem colocadas ao redor deles. Por exemplo, usar -- u pode gerar a string -InputObject sem usar aspas ou interpretá-la como um parâmetro:

Write-Output -- -InputObject
-InputObject

Ao contrário do token stop-parsing (--%), todos os valores após o -- token podem ser interpretados como expressões pelo PowerShell.

Write-Output -- -InputObject $env:PROCESSOR_ARCHITECTURE
-InputObject
AMD64

Esse comportamento só se aplica a comandos do PowerShell. Se você usar o -- token ao chamar um comando externo, a -- cadeia de caracteres será passada como um argumento para esse comando.

TestExe -echoargs -a -b -- -c

A saída mostra que -- é passado como um argumento para TestExe.

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

Til (~)

O caractere til (~) tem um significado especial no PowerShell. Quando ele é usado com comandos do PowerShell no início de um caminho, o caractere til é expandido para o diretório base do usuário. Se o caractere til for usado em qualquer outro lugar em um caminho, ele será tratado como um caractere literal.

PS D:\temp> $PWD

Path
----
D:\temp

PS D:\temp> Set-Location ~
PS C:\Users\user2> $PWD

Path
----
C:\Users\user2

Neste exemplo, o parâmetro Name do espera uma cadeia de New-Item caracteres. O caractere til é tratado como um caractere literal. Para mudar para o diretório recém-criado, você deve qualificar o caminho com o caractere til.

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\~

Quando você usa o caractere til com comandos nativos, o PowerShell passa o til como um caractere literal. Usar o til em um caminho causa erros para comandos nativos no Windows que não dão suporte ao caractere til.

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

Confira também