Partager via


about_Parsing

Description courte

Décrit comment PowerShell analyse les commandes.

Description longue

Lorsque vous entrez une commande à l’invite de commandes, PowerShell interrompt le texte de la commande en une série de segments appelés jetons , puis détermine comment interpréter chaque jeton.

Par exemple, si vous tapez :

Write-Host book

PowerShell interrompt la commande en deux jetons et Write-Host bookinterprète chaque jeton indépendamment à l’aide de l’un des deux modes d’analyse majeurs : le mode d’expression et le mode argument.

Remarque

Lorsque PowerShell analyse l’entrée de commande, elle tente de résoudre les noms de commandes en applets de commande ou exécutables natifs. Si un nom de commande n’a pas de correspondance exacte, PowerShell s’ajoute Get- à la commande en tant que verbe par défaut. Par exemple, PowerShell analyse Service en tant que Get-Service. Il n’est pas recommandé d’utiliser cette fonctionnalité pour les raisons suivantes :

  • C’est inefficace. Cela entraîne la recherche de PowerShell plusieurs fois.
  • Les programmes externes portant le même nom sont résolus en premier. Vous ne pouvez donc pas exécuter l’applet de commande prévue.
  • Get-Help et Get-Command ne reconnaissent pas les noms sans verbe.
  • Le nom de la commande peut être un mot réservé ou un mot clé de langue. Process est à la fois, et ne peut pas être résolu en Get-Process.

Mode expression

Le mode expression est destiné à combiner des expressions, requises pour la manipulation de valeurs dans un langage de script. Les expressions sont des représentations de valeurs dans la syntaxe PowerShell et peuvent être simples ou composites, par exemple :

Les expressions littérales sont des représentations directes de leurs valeurs :

'hello'
32

Les expressions de variable portent la valeur de la variable qu’elles référencent :

$x
$script:path

Les opérateurs combinent d’autres expressions pour l’évaluation :

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • Les littéraux de chaîne de caractères doivent être contenus entre guillemets .
  • Les nombres sont traités comme des valeurs numériques plutôt que comme une série de caractères (sauf en cas d’échappement).
  • Les opérateurs, y compris les opérateurs unaires comme - et -not les opérateurs binaires comme + et -gt, sont interprétés comme des opérateurs et appliquent leurs opérations respectives sur leurs arguments (opérandes).
  • Les expressions d’attribut et de conversion sont analysées en tant qu’expressions et appliquées aux expressions subordonnées. Par exemple : [int] '7'.
  • Les références de variables sont évaluées à leurs valeurs, mais la plaque est interdite et provoque une erreur d’analyseur.
  • Tout autre élément est traité comme une commande à appeler.

Mode Argument

Lors de l’analyse, PowerShell cherche d’abord à interpréter l’entrée en tant qu’expression. Toutefois, lorsqu’un appel de commande est rencontré, l’analyse continue en mode argument. Si vous avez des arguments qui contiennent des espaces, tels que des chemins d’accès, vous devez placer ces valeurs d’argument entre guillemets.

Le mode Argument est conçu pour l’analyse des arguments et des paramètres pour les commandes dans un environnement shell. Toutes les entrées sont traitées comme une chaîne extensible, sauf si elle utilise l’une des syntaxes suivantes :

  • Signe dollar ($) suivi d’un nom de variable commence une référence de variable, sinon il est interprété comme faisant partie de la chaîne extensible. La référence de variable peut inclure l’accès aux membres ou l’indexation.

    • Des caractères supplémentaires suivants des références de variables simples, telles que $HOME, sont considérés comme faisant partie du même argument. Placez le nom de la variable dans les accolades ({}) pour le séparer des caractères suivants. Par exemple : ${HOME}.
    • Lorsque la référence de variable inclut l’accès aux membres, le premier des caractères supplémentaires est considéré comme le début d’un nouvel argument. Par exemple$HOME.Length-more, deux arguments sont les suivants : la valeur du littéral -morede $HOME.Length chaîne .
  • Guillemets (' et ") chaînes de début

  • Accolades ({}) commencent un nouveau bloc de script

  • Les virgules (,) introduisent des listes passées sous forme de tableaux, sauf si la commande appelée est une application native, auquel cas elles sont interprétées comme faisant partie de la chaîne extensible. Les virgules initiales, consécutives ou de fin ne sont pas prises en charge.

  • Parenthèses (()) commencer une nouvelle expression

  • L’opérateur de sous-expression ($()) commence une expression incorporée

  • Initial at sign (@) commence les syntaxes d’expression telles que la mise en forme (), les tableaux (@args@(1,2,3)) et les littéraux de table de hachage (@{a=1;b=2}).

  • (), $()et @() au début d’un jeton, créez un contexte d’analyse qui peut contenir des expressions ou des commandes imbriquées.

    • Lorsqu’il est suivi de caractères supplémentaires, le premier caractère supplémentaire est considéré comme le début d’un nouvel argument distinct.
    • Lorsqu’il est précédé d’un littéral $() non cité fonctionne comme une chaîne extensible, () démarre un nouvel argument qui est une expression et @() est pris comme littéral @ avec () le démarrage d’un nouvel argument qui est une expression.
  • Tout le reste est traité comme une chaîne extensible, à l’exception des métacharacteurs qui ont toujours besoin d’échappement. Voir Gestion des caractères spéciaux.

    • Les métacharacters en mode argument (caractères ayant une signification syntactique spéciale) sont les suivants : <space> ' " ` , ; ( ) { } | & < > @ #. De ceux-ci, < > @ # ne sont spéciaux qu’au début d’un jeton.
  • Le jeton d’analyse d’arrêt (--%) modifie l’interprétation de tous les arguments restants. Pour plus d’informations, consultez la section du jeton d’analyse d’arrêt ci-dessous.

Exemples

Le tableau suivant fournit plusieurs exemples de jetons traités en mode expression et en mode argument et l’évaluation de ces jetons. Pour ces exemples, la valeur de la variable $a est 4.

Exemple Mode Result
2 Expression 2 (entier)
`2 Expression « 2 » (commande)
Write-Output 2 Expression 2 (entier)
2+2 Expression 4 (entier)
Write-Output 2+2 Argument « 2+2 » (chaîne)
Write-Output(2+2) Expression 4 (entier)
$a Expression 4 (entier)
Write-Output $a Expression 4 (entier)
$a+2 Expression 6 (entier)
Write-Output $a+2 Argument « 4+2 » (chaîne)
$- Argument « $- » (commande)
Write-Output $- Argument « $- » (chaîne)
a$a Expression « a$a » (commande)
Write-Output a$a Argument « a4 » (chaîne)
a'$a' Expression « a$a » (commande)
Write-Output a'$a' Argument « a$a » (chaîne)
a"$a" Expression « a$a » (commande)
Write-Output a"$a" Argument « a4 » (chaîne)
a$(2) Expression « a$(2) » (commande)
Write-Output a$(2) Argument « a2 » (chaîne)

Chaque jeton peut être interprété comme un type d’objet, tel que Boolean ou String. PowerShell tente de déterminer le type d’objet de l’expression. Le type d’objet dépend du type de paramètre attendu par une commande et de savoir si PowerShell sait comment convertir l’argument en type correct. Le tableau suivant présente plusieurs exemples de types attribués aux valeurs retournées par les expressions.

Exemple Mode Result
Write-Output !1 argument « !1 » (chaîne)
Write-Output (!1) expression False (booléen)
Write-Output (2) expression 2 (entier)
Set-Variable AB A,B argument 'A','B' (tableau)
CMD /CECHO A,B argument 'A,B' (chaîne)
CMD /CECHO $AB expression 'A B' (tableau)
CMD /CECHO :$AB argument ' :A B' (chaîne)

Gestion des caractères spéciaux

Le caractère backtick (`) peut être utilisé pour échapper à n’importe quel caractère spécial dans une expression. Cela est le plus utile pour échapper aux métacharacteurs en mode argument que vous souhaitez utiliser comme caractères littérals plutôt que comme métacharacteur. Par exemple, pour utiliser le signe dollar ($) comme littéral dans une chaîne extensible :

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

Continuation de ligne

Le caractère backtick peut également être utilisé à la fin d’une ligne pour vous permettre de continuer l’entrée sur la ligne suivante. Cela améliore la lisibilité d’une commande qui prend plusieurs paramètres avec des noms longs et des valeurs d’argument. Par exemple :

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

Toutefois, vous devez éviter d’utiliser la continuation de ligne.

  • Les caractères backtick peuvent être difficiles à voir et faciles à oublier.
  • Un espace supplémentaire après que le backtick interrompt la continuation de ligne. Étant donné que l’espace est difficile à voir, il peut être difficile de trouver l’erreur.

PowerShell fournit plusieurs façons d’interrompre les lignes à des points naturels de la syntaxe.

  • Après les caractères de canal (|)
  • Après les opérateurs binaires (+, -, -eqetc.)
  • Après des virgules (,) dans un tableau
  • Après avoir ouvert des caractères tels que [, , {(

Pour un jeu de paramètres volumineux, utilisez plutôt la mise en forme. Par exemple :

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

Transfert d’arguments à des commandes natives

Lors de l’exécution de commandes natives à partir de PowerShell, les arguments sont d’abord analysés par PowerShell. Les arguments analysés sont ensuite joints à une seule chaîne avec chaque paramètre séparé par un espace.

Par exemple, la commande suivante appelle le icacls.exe programme.

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

Pour exécuter cette commande dans PowerShell 2.0, vous devez utiliser des caractères d’échappement pour empêcher PowerShell de mal interpréter les parenthèses.

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

Jeton d’analyse d’arrêt

À compter de PowerShell 3.0, vous pouvez utiliser le jeton d’analyse d’arrêt (--%) pour empêcher PowerShell d’interpréter l’entrée en tant que commandes ou expressions PowerShell.

Remarque

Le jeton d’analyse d’arrêt est destiné uniquement à utiliser des commandes natives sur les plateformes Windows.

Lors de l’appel d’une commande native, placez le jeton d’analyse d’arrêt avant les arguments du programme. Cette technique est beaucoup plus facile que d’utiliser des caractères d’échappement pour éviter une mauvaise interprétation.

Lorsqu’il rencontre un jeton d’analyse d’arrêt, PowerShell traite les caractères restants de la ligne en tant que littéral. La seule interprétation qu’elle effectue consiste à remplacer les valeurs des variables d’environnement qui utilisent la notation Windows standard, telle que %USERPROFILE%.

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

PowerShell envoie la chaîne de commande suivante au icacls.exe programme :

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

Le jeton d’analyse d’arrêt n’est effectif que jusqu’au prochain caractère de ligne ou de pipeline. Vous ne pouvez pas utiliser le caractère de continuation de ligne (`) pour étendre son effet ou utiliser un délimiteur de commande (;) pour arrêter son effet.

En dehors des %variable% références de variable d’environnement, vous ne pouvez pas incorporer d’autres éléments dynamiques dans la commande. L’échappement d’un % caractère comme %%, comme vous pouvez le faire dans les fichiers batch, n’est pas pris en charge. %<name>% Les jetons sont invariablement développés. S’il <name> ne fait pas référence à une variable d’environnement définie, le jeton est transmis en l’état.

Vous ne pouvez pas utiliser la redirection de flux (par >file.txtexemple), car elles sont transmises en tant qu’arguments à la commande cible.

Dans l’exemple suivant, la première étape exécute une commande sans utiliser le jeton d’analyse d’arrêt. PowerShell évalue la chaîne entre guillemets et transmet la valeur (sans guillemets), cmd.exece qui entraîne une erreur.

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"

Remarque

Le jeton d’analyse d’arrêt n’est pas nécessaire lors de l’utilisation des applets de commande PowerShell. Toutefois, il peut être utile de passer des arguments à une fonction PowerShell conçue pour appeler une commande native avec ces arguments.

Passage d’arguments contenant des guillemets

Certaines commandes natives attendent des arguments qui contiennent des guillemets. PowerShell 7.3 a changé la façon dont la ligne de commande est analysée pour les commandes natives.

Attention

Le nouveau comportement est un changement cassant du comportement windows PowerShell 5.1. Il peut interrompre les scripts et l’automatisation qui contournent les différents problèmes pendant l’appel d’applications natives. Utilisez le jeton d’analyse d’arrêt (--%) ou l’applet Start-Process de commande pour éviter le passage de l’argument natif si nécessaire.

La nouvelle $PSNativeCommandArgumentPassing variable de préférence contrôle ce comportement. Cette variable vous permet de sélectionner le comportement au moment de l’exécution. Les valeurs valides sont Legacy, Standard et Windows. Le comportement par défaut est propre à la plateforme. Sur les plateformes Windows, le paramètre par défaut est Windows et Standard sur les plateformes non-Windows.

Legacy est le comportement historique. Le comportement des modes Windows et Standard est le même, sauf qu’en mode Windows, les appels des fichiers suivants utilisent automatiquement le passage de l’argument de style Legacy.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • se terminant par .bat
  • se terminant par .cmd
  • se terminant par .js
  • se terminant par .vbs
  • se terminant par .wsf

Si $PSNativeCommandArgumentPassing est défini sur Legacy ou Standard, l’analyseur ne recherche pas ces fichiers.

Remarque

Les exemples suivants utilisent l’outil TestExe.exe. Vous pouvez générer TestExe à partir du code source. Consultez TestExe dans le référentiel source PowerShell.

Nouveaux comportements mis à disposition par ce changement :

  • Les chaînes littérales ou extensibles avec des guillemets incorporés sont maintenant conservées :

    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>
    
  • Les chaînes vides en tant qu’arguments sont maintenant conservées :

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

L’objectif de ces exemples est de passer le chemin d’accès du répertoire (avec des espaces et des guillemets) "C:\Program Files (x86)\Microsoft\" à une commande native afin qu’il ait reçu le chemin sous forme de chaîne entre guillemets.

En mode ou Standard en Windows mode, les exemples suivants produisent les résultats attendus :

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

Pour obtenir les mêmes résultats en Legacy mode, vous devez échapper aux guillemets ou utiliser le jeton d’analyse d’arrêt (--%) :

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

Remarque

La barre oblique inverse (\) n’est pas reconnue comme caractère d’échappement par PowerShell. Il s’agit du caractère d’échappement utilisé par l’API sous-jacente pour ProcessStartInfo.ArgumentList.

PowerShell 7.3 a également ajouté la possibilité de tracer la liaison de paramètres pour les commandes natives. Pour plus d’informations, consultez Trace-Command.

Passage d’arguments à des commandes PowerShell

À compter de PowerShell 3.0, vous pouvez utiliser le jeton de fin de paramètres (--) pour empêcher PowerShell d’interpréter l’entrée en tant que paramètres PowerShell. Il s’agit d’une convention spécifiée dans la spécification POSIX Shell et Utilities.

Jeton de fin de paramètres

Le jeton de fin de paramètres (--) indique que tous les arguments suivants doivent être passés sous leur forme réelle, comme si les guillemets doubles étaient placés autour d’eux. Par exemple, -- vous pouvez générer la chaîne -InputObject sans utiliser de guillemets ou l’avoir interprétée comme un paramètre :

Write-Output -- -InputObject
-InputObject

Contrairement au jeton d’analyse d’arrêt (--%), toutes les valeurs qui suivent le -- jeton peuvent être interprétées comme des expressions par PowerShell.

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

Ce comportement s’applique uniquement aux commandes PowerShell. Si vous utilisez le jeton lors de l’appel -- d’une commande externe, la -- chaîne est passée en tant qu’argument à cette commande.

TestExe -echoargs -a -b -- -c

La sortie indique qu’elle -- est passée en tant qu’argument à TestExe.

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

Tilde (~)

Le caractère tilde (~) a une signification particulière dans PowerShell. Lorsqu’il est utilisé avec des commandes PowerShell au début d’un chemin d’accès, le caractère tilde est étendu au répertoire de base de l’utilisateur. Si le caractère tilde est utilisé n’importe où dans un chemin d’accès, il est traité comme un caractère littéral.

PS D:\temp> $PWD

Path
----
D:\temp

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

Path
----
C:\Users\user2

Dans cet exemple, le paramètre Name de la New-Item chaîne attend une chaîne. Le caractère tilde est traité comme un caractère littéral. Pour passer au répertoire nouvellement créé, vous devez qualifier le chemin d’accès avec le caractère 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\~

Lorsque vous utilisez le caractère tilde avec des commandes natives, PowerShell passe le tilde en tant que caractère littéral. L’utilisation du tilde dans un chemin entraîne des erreurs pour les commandes natives sur Windows qui ne prennent pas en charge le caractère 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

Voir aussi