about_Parsing
Descripción breve
Describe cómo PowerShell analiza los comandos.
Descripción larga
Al escribir un comando en el símbolo del sistema, PowerShell divide el texto del comando en una serie de segmentos denominados tokens y, a continuación, determina cómo interpretar cada token.
Por ejemplo, si escribe:
Write-Host book
PowerShell divide el comando en dos tokens y Write-Host
book
, e interpreta cada token de forma independiente mediante uno de los dos modos de análisis principales: el modo de expresión y el modo de argumento.
Nota:
A medida que PowerShell analiza la entrada del comando, intenta resolver los nombres de comando en cmdlets o ejecutables nativos. Si un nombre de comando no tiene una coincidencia exacta, PowerShell antepone Get-
el comando como verbo predeterminado. Por ejemplo, PowerShell analiza Service
como Get-Service
. No se recomienda usar esta característica por los siguientes motivos:
- Es ineficaz. Esto hace que PowerShell busque varias veces.
- Los programas externos con el mismo nombre se resuelven primero, por lo que es posible que no ejecute el cmdlet previsto.
Get-Help
yGet-Command
no reconocen nombres sin verbo.- El nombre del comando puede ser una palabra reservada o una palabra clave de lenguaje.
Process
es y no se puede resolver enGet-Process
.
Modo de expresión
El modo de expresión está diseñado para combinar expresiones, necesarias para la manipulación de valores en un lenguaje de scripting. Las expresiones son representaciones de valores en la sintaxis de PowerShell y pueden ser simples o compuestas, por ejemplo:
Las expresiones literales son representaciones directas de sus valores:
'hello'
32
Las expresiones de variable llevan el valor de la variable a la que hacen referencia:
$x
$script:path
Los operadores combinan otras expresiones para la evaluación:
-12
-not $Quiet
3 + 7
$input.Length -gt 1
- Los literales de cadena de caracteres deben incluirse entre comillas.
- Los números se tratan como valores numéricos en lugar de como una serie de caracteres (a menos que se escapen).
- Los operadores, incluidos los operadores unarios como
-
y-not
los operadores binarios como+
y ,-gt
se interpretan como operadores y aplican sus respectivas operaciones en sus argumentos (operandos). - Las expresiones de atributo y conversión se analizan como expresiones y se aplican a expresiones subordinadas. Por ejemplo:
[int] '7'
. - Las referencias de variable se evalúan en sus valores, pero la expansión está prohibida y produce un error de analizador.
- Todo lo demás se trata como un comando que se va a invocar.
Modo de argumento
Al analizar, PowerShell primero busca interpretar la entrada como una expresión. Pero cuando se encuentra una invocación de comando, el análisis continúa en modo de argumento. Si tiene argumentos que contienen espacios, como rutas de acceso, debe incluir esos valores de argumento entre comillas.
El modo de argumento está diseñado para analizar argumentos y parámetros para comandos en un entorno de shell. Toda la entrada se trata como una cadena expandible a menos que use una de las sintaxis siguientes:
El signo de dólar (
$
) seguido de un nombre de variable comienza una referencia de variable; de lo contrario, se interpreta como parte de la cadena expandible. La referencia de variable puede incluir el acceso a miembros o la indexación.- Los caracteres adicionales siguientes a referencias de variables simples, como
$HOME
, se consideran parte del mismo argumento. Incluya el nombre de la variable entre llaves ({}
) para separarlo de los caracteres posteriores. Por ejemplo,${HOME}
. - Cuando la referencia de variable incluye el acceso a miembros, el primero de los caracteres adicionales se considera el inicio de un nuevo argumento. Por ejemplo
$HOME.Length-more
, da como resultado dos argumentos: el valor de y el literal-more
de$HOME.Length
cadena .
- Los caracteres adicionales siguientes a referencias de variables simples, como
Comillas (
'
y"
) comienzan las cadenasLlaves (
{}
) comienzan un nuevo bloque de scriptLas comas (
,
) presentan listas pasadas como matrices, a menos que el comando al que se llame sea una aplicación nativa, en cuyo caso se interpretan como parte de la cadena expandible. No se admiten comas iniciales, consecutivas o finales.Paréntesis (
()
) comienza una nueva expresiónOperador Subexpression (
$()
) comienza una expresión incrustadaInicial en signo (
@
) comienza sintaxis de expresión como la expansión (), matrices (@args
@(1,2,3)
) y literales de tabla hash (@{a=1;b=2}
).()
,$()
y@()
al principio de un token, se crea un nuevo contexto de análisis que puede contener expresiones o comandos anidados.- Cuando va seguido de caracteres adicionales, el primer carácter adicional se considera el inicio de un nuevo argumento independiente.
- Cuando un literal
$()
no comillado funciona como una cadena expandible,()
inicia un nuevo argumento que es una expresión y@()
se toma como literal@
con()
el inicio de un nuevo argumento que es una expresión.
Todo lo demás se trata como una cadena expandible, excepto metacharacters que todavía necesitan escapar. Consulte Control de caracteres especiales.
- Los metacaractores en modo de argumento (caracteres con significado sintáctico especial) son:
<space> ' " ` , ; ( ) { } | & < > @ #
. De estos,< > @ #
solo son especiales al principio de un token.
- Los metacaractores en modo de argumento (caracteres con significado sintáctico especial) son:
El token de detención del análisis (
--%
) cambia la interpretación de todos los argumentos restantes. Para obtener más información, consulte la sección token de detención del análisis a continuación.
Ejemplos
En la tabla siguiente se proporcionan varios ejemplos de tokens procesados en modo de expresión y modo de argumento y la evaluación de esos tokens. Para estos ejemplos, el valor de la variable $a
es 4
.
Ejemplo | Mode | Resultado |
---|---|---|
2 |
Expression | 2 (entero) |
`2 |
Expression | "2" (comando) |
Write-Output 2 |
Expression | 2 (entero) |
2+2 |
Expression | 4 (entero) |
Write-Output 2+2 |
Argument | "2+2" (cadena) |
Write-Output(2+2) |
Expression | 4 (entero) |
$a |
Expression | 4 (entero) |
Write-Output $a |
Expression | 4 (entero) |
$a+2 |
Expression | 6 (entero) |
Write-Output $a+2 |
Argument | "4+2" (cadena) |
$- |
Argument | "$-" (comando) |
Write-Output $- |
Argument | "$-" (cadena) |
a$a |
Expression | "a$a" (comando) |
Write-Output a$a |
Argument | "a4" (cadena) |
a'$a' |
Expression | "a$a" (comando) |
Write-Output a'$a' |
Argument | "a$a" (cadena) |
a"$a" |
Expression | "a$a" (comando) |
Write-Output a"$a" |
Argument | "a4" (cadena) |
a$(2) |
Expression | "a$(2)" (comando) |
Write-Output a$(2) |
Argument | "a2" (cadena) |
Cada token se puede interpretar como un tipo de objeto, como Boolean o String. PowerShell intenta determinar el tipo de objeto de la expresión. El tipo de objeto depende del tipo de parámetro que espera un comando y de si PowerShell sabe cómo convertir el argumento al tipo correcto. En la tabla siguiente se muestran varios ejemplos de los tipos asignados a los valores devueltos por las expresiones.
Ejemplo | Mode | Resultado |
---|---|---|
Write-Output !1 |
argument | "!1" (cadena) |
Write-Output (!1) |
expression | False (booleano) |
Write-Output (2) |
expression | 2 (entero) |
Set-Variable AB A,B |
argument | 'A','B' (matriz) |
CMD /CECHO A,B |
argument | 'A,B' (cadena) |
CMD /CECHO $AB |
expression | 'A B' (matriz) |
CMD /CECHO :$AB |
argument | ':A B' (cadena) |
Tratamiento de caracteres especiales
El carácter de barra inversa (`
) se puede usar para escapar cualquier carácter especial en una expresión. Esto resulta más útil para escapar de los metacharacters en modo de argumento que se quieren usar como caracteres literales en lugar de como metacaracter. Por ejemplo, para usar el signo de dólar ($
) como literal en una cadena expandible:
"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.
Continuación de línea
El carácter de barra trasera también se puede usar al final de una línea para permitir continuar la entrada en la línea siguiente. Esto mejora la legibilidad de un comando que toma varios parámetros con nombres largos y valores de argumento. Por ejemplo:
New-AzVm `
-ResourceGroupName "myResourceGroupVM" `
-Name "myVM" `
-Location "EastUS" `
-VirtualNetworkName "myVnet" `
-SubnetName "mySubnet" `
-SecurityGroupName "myNetworkSecurityGroup" `
-PublicIpAddressName "myPublicIpAddress" `
-Credential $cred
Sin embargo, debe evitar el uso de la continuación de línea.
- Los caracteres versos pueden ser difíciles de ver y fáciles de olvidar.
- Un espacio adicional después de que la barra trasera rompa la continuación de la línea. Dado que el espacio es difícil de ver puede ser difícil encontrar el error.
PowerShell proporciona varias formas de interrumpir líneas en puntos naturales en la sintaxis.
- Después de los caracteres de canalización (
|
) - Después de los operadores binarios (
+
,-
,-eq
, etc.) - Después de comas (
,
) en una matriz - Después de abrir caracteres como
[
,{
,(
En el caso del conjunto de parámetros grandes, use la expansión en su lugar. Por ejemplo:
$parameters = @{
ResourceGroupName = "myResourceGroupVM"
Name = "myVM"
Location = "EastUS"
VirtualNetworkName = "myVnet"
SubnetName = "mySubnet"
SecurityGroupName = "myNetworkSecurityGroup"
PublicIpAddressName = "myPublicIpAddress"
Credential = $cred
}
New-AzVm @parameters
Paso de argumentos a comandos nativos
Al ejecutar comandos nativos desde PowerShell, PowerShell analiza primero los argumentos. A continuación, los argumentos analizados se combinan en una sola cadena con cada parámetro separado por un espacio.
Por ejemplo, el siguiente comando llama al icacls.exe
programa.
icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F
Para ejecutar este comando en PowerShell 2.0, debe usar caracteres de escape para evitar que PowerShell malinterprete los paréntesis.
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F
Token de detención del análisis
A partir de PowerShell 3.0, puede usar el token de detención (--%
) para impedir que PowerShell interprete la entrada como comandos o expresiones de PowerShell.
Nota:
El token de detención del análisis solo está pensado para usar comandos nativos en plataformas Windows.
Al llamar a un comando nativo, coloque el token de detención del análisis antes de los argumentos del programa. Esta técnica es mucho más fácil que usar caracteres de escape para evitar errores de interpretación.
Cuando encuentra un token de detención del análisis, PowerShell trata los caracteres restantes de la línea como literal. La única interpretación que realiza es sustituir los valores de las variables de entorno que usan la notación estándar de Windows, como %USERPROFILE%
.
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F
PowerShell envía la siguiente cadena de comandos al icacls.exe
programa:
X:\VMS /grant Dom\HVAdmin:(CI)(OI)F
El token de detención del análisis solo es efectivo hasta el siguiente carácter de nueva línea o canalización. No puede usar el carácter de continuación de línea (`
) para extender su efecto o usar un delimitador de comandos (;
) para finalizar su efecto.
Aparte de %variable%
las referencias de variables de entorno, no puede insertar ningún otro elemento dinámico en el comando. No se admite el escape de un %
carácter como %%
, la forma en que puede hacerlo dentro de los archivos por lotes. %<name>%
los tokens se expanden invariablemente. Si <name>
no hace referencia a una variable de entorno definida, el token se pasa tal como está.
No puede usar el redireccionamiento de secuencias (como >file.txt
) porque se pasan textualmente como argumentos al comando de destino.
En el ejemplo siguiente, el primer paso ejecuta un comando sin usar el token de detención del análisis. PowerShell evalúa la cadena entre comillas y pasa el valor (sin comillas) a cmd.exe
, lo que produce un error.
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"
Nota:
El token de detención del análisis no es necesario cuando se usan cmdlets de PowerShell. Sin embargo, podría resultar útil pasar argumentos a una función de PowerShell diseñada para llamar a un comando nativo con esos argumentos.
Paso de argumentos que contienen caracteres de comillas
Algunos comandos nativos esperan argumentos que contienen caracteres de comillas. PowerShell 7.3 cambió la forma en que se analiza la línea de comandos para los comandos nativos.
Precaución
El nuevo comportamiento es un cambio importante del comportamiento de Windows PowerShell 5.1. Puede provocar la interrupción de los scripts y la automatización que se usan como soluciones alternativas para diferentes problemas al invocar aplicaciones nativas. Use el token de detención del análisis (--%
) o el cmdlet para evitar que el Start-Process
argumento nativo pase cuando sea necesario.
La nueva $PSNativeCommandArgumentPassing
variable de preferencia controla este comportamiento. Esta variable permite seleccionar el comportamiento durante el runtime. Los valores válidos son Legacy
, Standard
y Windows
. El comportamiento predeterminado es específico de cada plataforma. En plataformas Windows la configuración predeterminada es Windows
y las plataformas no Windows adoptan el valor predeterminado Standard
.
Legacy
es el comportamiento que se ha usado hasta ahora. El comportamiento de los modos Windows
y Standard
es el mismo con la excepción de que, en modo Windows
, las invocaciones de los archivos siguientes usan automáticamente el paso de argumentos de estilo Legacy
.
cmd.exe
cscript.exe
wscript.exe
- termina en
.bat
- termina en
.cmd
- termina en
.js
- termina en
.vbs
- termina en
.wsf
Si $PSNativeCommandArgumentPassing
se establece en Legacy
o Standard
, el analizador no comprueba estos archivos.
Nota:
Los ejemplos siguientes usan la herramienta TestExe.exe
. Puede compilar TestExe
a partir del código fuente. Consulte TestExe en el repositorio de origen de PowerShell.
Nuevos comportamientos disponibles con este cambio:
Las cadenas literales o expandibles con comillas insertadas ahora se conservan:
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>
Las cadenas vacías usadas como argumentos ahora se conservan:
PS> TestExe -echoargs '' a b '' Arg 0 is <> Arg 1 is <a> Arg 2 is <b> Arg 3 is <>
El objetivo de estos ejemplos es pasar la ruta de acceso del directorio (con espacios y comillas) "C:\Program Files (x86)\Microsoft\"
a un comando nativo para que reciba la ruta de acceso como una cadena entre comillas.
En Windows
el modo o Standard
, los ejemplos siguientes generan los resultados esperados:
TestExe -echoargs """${env:ProgramFiles(x86)}\Microsoft\"""
TestExe -echoargs '"C:\Program Files (x86)\Microsoft\"'
Para obtener los mismos resultados en Legacy
modo, debe escapar las comillas o usar el token de detención del análisis (--%
):
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\\""
Nota:
PowerShell no reconoce el carácter de barra diagonal inversa (\
) como carácter de escape. Es el carácter de escape que usa la API subyacente para ProcessStartInfo.ArgumentList.
PowerShell 7.3 también agregó la capacidad de realizar un seguimiento del enlace de parámetros para comandos nativos. Para más información, vea Trace-Command.
Pasar argumentos a comandos de PowerShell
A partir de PowerShell 3.0, puede usar el token de fin de parámetros (--
) para impedir que PowerShell interprete la entrada como parámetros de PowerShell. Se trata de una convención especificada en la especificación de utilidades y shell de POSIX.
Token de fin de parámetros
El token de fin de parámetros (--
) indica que todos los argumentos que siguen deben pasarse en su forma real como si las comillas dobles se colocaran alrededor de ellos. Por ejemplo, el uso --
de puede generar la cadena -InputObject
sin usar comillas ni interpretarla como parámetro:
Write-Output -- -InputObject
-InputObject
A diferencia del token de detención del análisis (--%
), PowerShell puede interpretar los valores siguientes al --
token como expresiones.
Write-Output -- -InputObject $env:PROCESSOR_ARCHITECTURE
-InputObject
AMD64
Este comportamiento solo se aplica a los comandos de PowerShell. Si usa el --
token al llamar a un comando externo, la --
cadena se pasa como argumento a ese comando.
TestExe -echoargs -a -b -- -c
La salida muestra que --
se pasa como argumento a TestExe
.
Arg 0 is <-a>
Arg 1 is <-b>
Arg 2 is <-->
Arg 3 is <-c>
Tilde (~)
El carácter de tilde (~
) tiene un significado especial en PowerShell. Cuando se usa con comandos de PowerShell al principio de una ruta de acceso, el carácter tilde se expande al directorio principal del usuario. Si el carácter de tilde se usa en cualquier otro lugar de una ruta de acceso, se trata como un carácter literal.
PS D:\temp> $PWD
Path
----
D:\temp
PS D:\temp> Set-Location ~
PS C:\Users\user2> $PWD
Path
----
C:\Users\user2
En este ejemplo, el parámetro Name de New-Item
espera una cadena. El carácter de tilde se trata como un carácter literal. Para cambiar al directorio recién creado, debe calificar la ruta de acceso con el carácter tilde.
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\~
Cuando se usa el carácter de tilde con comandos nativos, PowerShell pasa la tilde como un carácter literal. El uso de la tilde en una ruta de acceso provoca errores para comandos nativos en Windows que no admiten el carácter tilde.
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