Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Il existe de nombreuses façons d’utiliser des variables dans des chaînes. J’appelle cette substitution de variable, mais je fais référence à chaque fois que vous souhaitez mettre en forme une chaîne pour inclure des valeurs à partir de variables. C’est quelque chose que je trouve souvent expliquer aux nouveaux scripteurs.
Remarque
La version originale de cet article est parue sur le blog écrit par @KevinMarquette. L’équipe PowerShell remercie Kevin de partager ce contenu avec nous. Consultez son blog à l’adresse PowerShellExplained.com.
Concaténation
La première classe de méthodes peut être appelée concaténation. C’est essentiellement prendre plusieurs chaînes et les joindre ensemble. Il existe une longue histoire d’utilisation de la concaténation pour générer des chaînes mises en forme.
$name = 'Kevin Marquette'
$message = 'Hello, ' + $name
La concaténation fonctionne correctement lorsqu’il n’y a que quelques valeurs à ajouter. Mais cela peut se compliquer rapidement.
$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'
Cet exemple simple est déjà plus difficile à lire.
Substitution de variable
PowerShell offre une autre option plus facile. Vous pouvez spécifier vos variables directement dans les chaînes.
$message = "Hello, $first $last."
Le type de guillemets que vous utilisez autour de la chaîne fait une différence. Une chaîne entre guillemets doubles autorise la substitution, mais une seule chaîne entre guillemets n’est pas possible. Il y a des fois que vous voulez l’un ou l’autre afin que vous ayez une option.
Substitution de commande
Les choses se compliquent un peu lorsque vous commencez à essayer d’obtenir les valeurs des propriétés dans une chaîne. C’est là que beaucoup de nouvelles personnes se sont tripées. Tout d’abord, laissez-moi vous montrer ce qu’ils pensent devraient travailler (et à la valeur faciale ressemble presque à ce qu’il devrait).
$directory = Get-Item 'C:\windows'
$message = "Time: $directory.CreationTime"
Vous vous attendiez à obtenir le CreationTime off du $directory, mais au lieu de cela vous obtenez Time: C:\windows.CreationTime comme valeur. C’est pourquoi ce type de substitution ne voit que la variable de base. Il considère la période dans le cadre de la chaîne afin qu’elle cesse de résoudre la valeur plus profonde.
Il arrive simplement que cet objet donne une chaîne en tant que valeur par défaut lorsqu’il est placé dans une chaîne.
Certains objets vous donnent le nom de type à la place System.Collections.Hashtable. Juste quelque chose à regarder.
PowerShell vous permet d’exécuter des commandes à l’intérieur de la chaîne avec une syntaxe spéciale. Cela nous permet d’obtenir les propriétés de ces objets et d’exécuter toute autre commande pour obtenir une valeur.
$message = "Time: $($directory.CreationTime)"
Cela fonctionne très bien pour certaines situations, mais il peut être aussi fou que la concaténation si vous avez seulement quelques variables.
Exécution des commandes
Vous pouvez exécuter des commandes à l’intérieur d’une chaîne. Même si j’ai cette option, je n’aime pas ça. Il est rapidement et difficile à déboguer. J’exécute la commande et je l’enregistre dans une variable ou j’utilise une chaîne de format.
$message = "Date: $(Get-Date)"
Chaîne de format
.NET a un moyen de mettre en forme des chaînes que je trouve assez facile à utiliser. Tout d’abord, laissez-moi vous montrer la méthode statique pour celle-ci avant de vous montrer le raccourci PowerShell pour faire la même chose.
# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)
# PowerShell format string
'Hello, {0} {1}.' -f $first, $last
Ce qui se passe ici est que la chaîne est analysée pour les jetons {0} , {1}puis qu’elle utilise ce nombre pour choisir parmi les valeurs fournies. Si vous souhaitez répéter une valeur dans la chaîne, vous pouvez réutiliser ce nombre de valeurs.
Plus la chaîne est compliquée, plus vous obtenez de valeur de cette approche.
Mettre en forme des valeurs en tant que tableaux
Si votre ligne de format est trop longue, vous pouvez d’abord placer vos valeurs dans un tableau.
$values = @(
"Kevin"
"Marquette"
)
'Hello, {0} {1}.' -f $values
Ce n’est pas une plate-forme parce que je passe tout le tableau dans, mais l’idée est similaire.
Mise en forme avancée
J’ai intentionnellement appelé ceux-ci comme provenant de .NET parce qu’il y a beaucoup d’options de mise en forme déjà bien documentées dessus. Il existe des façons intégrées de mettre en forme différents types de données.
"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f 8175133
20211110
Population 8,175,133
Je ne vais pas les entrer, mais je voulais juste vous informer que c’est un moteur de mise en forme très puissant si vous en avez besoin.
Jointure de chaînes
Parfois, vous souhaitez concaténer une liste de valeurs ensemble. Il y a un -join opérateur qui peut le faire pour vous. Il vous permet même de spécifier un caractère à joindre entre les chaînes.
$servers = @(
'server1'
'server2'
'server3'
)
$servers -join ','
Si vous souhaitez utiliser -join certaines chaînes sans séparateur, vous devez spécifier une chaîne ''vide.
Mais si c’est tout ce dont vous avez besoin, il existe une option plus rapide.
[string]::Concat('server1','server2','server3')
[string]::Concat($servers)
Il est également utile de souligner que vous pouvez également -split des chaînes.
Join-Path
Cela est souvent négligé, mais une applet de commande idéale pour la création d’un chemin d’accès au fichier.
$folder = 'Temp'
Join-Path -Path 'C:\windows' -ChildPath $folder
La grande chose à ce sujet est qu’il fonctionne correctement les barres obliques inverses quand il met les valeurs ensemble. Cela est particulièrement important si vous prenez des valeurs à partir d’utilisateurs ou de fichiers config.
Cela va aussi bien avec Split-Path et Test-Path. Je les aborde également dans mon billet sur la lecture et l’enregistrement dans les fichiers.
Les chaînes sont des tableaux
Je dois mentionner l’ajout de chaînes ici avant de continuer. N’oubliez pas qu’une chaîne n’est qu’un tableau de caractères. Lorsque vous ajoutez plusieurs chaînes ensemble, un nouveau tableau est créé à chaque fois.
Examinez cet exemple :
$message = "Numbers: "
foreach($number in 1..10000)
{
$message += " $number"
}
Il semble très simple, mais ce que vous ne voyez pas est que chaque fois qu’une chaîne est ajoutée à $message celle-ci, une nouvelle chaîne entière est créée. La mémoire est allouée, les données sont copiées et l’ancienne est ignorée.
Pas un gros problème quand il n’est fait que quelques fois, mais une boucle comme cela exposerait vraiment le problème.
StringBuilder
StringBuilder est également très populaire pour la création de chaînes volumineuses à partir de nombreuses chaînes plus petites. La raison pour laquelle c’est parce qu’il collecte simplement toutes les chaînes que vous y ajoutez et concatène uniquement toutes ces chaînes à la fin lorsque vous récupérez la valeur.
$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"
[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
[void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()
Là encore, c’est quelque chose que j’ai atteint .NET pour. Je ne l’utilise plus souvent, mais c’est bon de le savoir.
Délimitation avec accolades
Cela est utilisé pour la concaténation de suffixes dans la chaîne. Parfois, votre variable n’a pas de limite de mot propre.
$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"
Merci Redditor u/real_parbold pour celui-ci.
Voici une alternative à cette approche :
Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester
J’utilise personnellement la chaîne de format pour cela, mais il est bon de savoir si vous le voyez dans la nature.
Rechercher et remplacer des jetons
Bien que la plupart de ces fonctionnalités limitent votre besoin de déployer votre propre solution, il arrive que vous ayez des fichiers de modèles volumineux dans lesquels vous souhaitez remplacer des chaînes à l’intérieur.
Supposons que vous avez extrait un modèle à partir d’un fichier qui a beaucoup de texte.
$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'
Vous pouvez avoir beaucoup de jetons à remplacer. L’astuce consiste à utiliser un jeton très distinct qui est facile à trouver et remplacer. J’ai tendance à utiliser un caractère spécial aux deux extrémités pour aider à le distinguer.
J’ai récemment trouvé une nouvelle façon d’aborder ce problème. J’ai décidé de laisser cette section ici parce que c’est un modèle qui est couramment utilisé.
Remplacer plusieurs jetons
Lorsque j’ai une liste de jetons que je dois remplacer, je prends une approche plus générique. Je les placerais dans une table de hachage et itérer sur eux pour faire le remplacement.
$tokenList = @{
Full_Name = 'Kevin Marquette'
Location = 'Orange County'
State = 'CA'
}
$letter = Get-Content -Path TemplateLetter.txt -RAW
foreach( $token in $tokenList.GetEnumerator() )
{
$pattern = '#{0}#' -f $token.key
$letter = $letter -replace $pattern, $token.Value
}
Ces jetons peuvent être chargés à partir de JSON ou CSV si nécessaire.
ExecutionContext ExpandString
Il existe un moyen intelligent de définir une chaîne de substitution avec des guillemets simples et d’étendre les variables ultérieurement. Examinez cet exemple :
$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)
L’appel au InvokeCommand.ExpandString contexte d’exécution actuel utilise les variables de l’étendue actuelle pour la substitution. La chose clé ici est que les $message variables peuvent être définies très tôt avant même l’existence des variables.
Si nous développons cela un peu, nous pouvons effectuer cette substitution par rapport à différentes valeurs.
$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
$ExecutionContext.InvokeCommand.ExpandString($message)
}
Pour continuer cette idée ; vous pouvez importer un modèle de courrier volumineux à partir d’un fichier texte pour effectuer cette opération. Je dois remercier Mark Kraus pour cette suggestion.
Quel que soit le meilleur pour vous
Je suis un fan de l’approche de chaîne de format. Je le fais certainement avec les chaînes plus complexes ou s’il existe plusieurs variables. Sur tout ce qui est très court, je peux utiliser l’un de ces éléments.
Autre chose?
J’ai couvert beaucoup de terrain sur celui-ci. J’espère que vous allez apprendre quelque chose de nouveau.
Liens
Si vous souhaitez en savoir plus sur les méthodes et fonctionnalités qui rendent l’interpolation de chaîne possible, consultez la liste suivante pour la documentation de référence.
- La concaténation utilise l’opérateur d’ajout
- La substitution de variables et de commandes suit les règles de guillemets
- La mise en forme utilise l’opérateur de format
- La jointure de chaînes utilise l’opérateur de jointure et les références
Join-Path, mais vous pouvez également en savoir plus surJoin-String - Les tableaux sont documentés dans About arrays
- StringBuilder est une classe .NET, avec sa propre documentation
- Les accolades dans les chaînes sont également couvertes dans les règles de guillemets
- Le remplacement de jeton utilise l’opérateur replace
- La méthode contient une documentation de référence sur l’API
$ExecutionContext.InvokeCommand.ExpandString().NET