Freigeben über


Alles, was Sie über die Variablenersetzung in Zeichenfolgen wissen wollten

Es gibt viele Möglichkeiten, Variablen in Zeichenfolgen zu verwenden. Ich aufrufe diese Variablenersetzung, aber ich beziehe mich auf jedes Mal, wenn Sie eine Zeichenfolge formatieren möchten, um Werte aus Variablen einzuschließen. Das ist etwas, das ich oft neuen Skriptern erklären kann.

Hinweis

Die Originalversion dieses Artikels erschien auf dem Blog, der von @KevinMarquettegeschrieben wurde. Das PowerShell-Team danke Kevin für das Teilen dieser Inhalte mit uns. Bitte schauen Sie sich seinen Blog bei PowerShellExplained.coman.

Verkettung

Die erste Klasse von Methoden kann als Verkettung bezeichnet werden. Es nimmt im Grunde mehrere Zeichenfolgen und verbindet sie zusammen. Es gibt eine lange Geschichte der Verwendung von Verkettungen zum Erstellen formatierter Zeichenfolgen.

$name = 'Kevin Marquette'
$message = 'Hello, ' + $name

Die Verkettung funktioniert in Ordnung, wenn nur ein paar Werte hinzugefügt werden sollen. Aber dies kann schnell kompliziert werden.

$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'

Dieses einfache Beispiel wird bereits schwieriger zu lesen.

Variablenersetzung

PowerShell verfügt über eine weitere Option, die einfacher ist. Sie können Ihre Variablen direkt in den Zeichenfolgen angeben.

$message = "Hello, $first $last."

Der Typ von Anführungszeichen, die Sie um die Zeichenfolge herum verwenden, macht einen Unterschied. Eine doppelte Zeichenfolge mit Anführungszeichen ermöglicht die Ersetzung, aber eine einzelne Zeichenfolge mit Anführungszeichen nicht. Es gibt Zeiten, in denen Sie eine oder andere haben, damit Sie eine Option haben.

Ersetzung von Befehlen

Die Dinge werden etwas schwierig, wenn Sie mit dem Versuch beginnen, die Werte von Eigenschaften in eine Zeichenfolge zu erhalten. Dort werden viele neue Leute aufgetaucht. Zunächst möchte ich Ihnen zeigen, was sie denken sollten (und bei Nennwert sieht fast so aus wie es sein sollte).

$directory = Get-Item 'C:\windows'
$message = "Time: $directory.CreationTime"

Sie würden davon ausgehen, dass Sie dies CreationTime aus dem $directoryWeg bringen, aber stattdessen erhalten Sie dies Time: C:\windows.CreationTime als Ihren Wert. Der Grund dafür ist, dass diese Art von Ersetzung nur die Basisvariable sieht. Er betrachtet den Punkt als Teil der Zeichenfolge, sodass er die Auflösung des Werts nicht mehr tiefer anhält.

Es geschieht einfach, dass dieses Objekt eine Zeichenfolge als Standardwert angibt, wenn es in eine Zeichenfolge eingefügt wird. Einige Objekte geben Ihnen stattdessen den Typnamen wie System.Collections.Hashtable. Nur etwas zu beobachten.

PowerShell ermöglicht Ihnen die Ausführung von Befehlen innerhalb der Zeichenfolge mit einer speziellen Syntax. Auf diese Weise können wir die Eigenschaften dieser Objekte abrufen und einen beliebigen anderen Befehl ausführen, um einen Wert abzurufen.

$message = "Time: $($directory.CreationTime)"

Dies funktioniert gut für einige Situationen, aber es kann genauso verrückt sein wie Verkettung, wenn Sie nur wenige Variablen haben.

Befehlsausführung

Sie können Befehle innerhalb einer Zeichenfolge ausführen. Obwohl ich diese Option habe, mag ich es nicht. Es wird schnell und schwer zu debuggen. Ich führe entweder den Befehl aus und speichere in einer Variablen oder verwende eine Formatzeichenfolge.

$message = "Date: $(Get-Date)"

Formatzeichenfolge

.NET verfügt über eine Möglichkeit zum Formatieren von Zeichenfolgen, mit denen ich recht einfach arbeiten kann. Lassen Sie mich zunächst die statische Methode dafür anzeigen, bevor ich Ihnen die PowerShell-Verknüpfung zum gleichen Zweck zeige.

# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)

# PowerShell format string
'Hello, {0} {1}.' -f $first, $last

Was hier geschieht, ist, dass die Zeichenfolge für die Token {0} analysiert wird, und {1}dann wird diese Zahl verwendet, um aus den bereitgestellten Werten zu wählen. Wenn Sie einen Wert in der Zeichenfolge wiederholen möchten, können Sie diese Zahl wiederverwenden.

Je komplizierter die Zeichenfolge wird, desto mehr Wert erhalten Sie aus diesem Ansatz.

Formatieren von Werten als Arrays

Wenn die Formatzeile zu lang wird, können Sie die Werte zuerst in ein Array setzen.

$values = @(
    "Kevin"
    "Marquette"
)
'Hello, {0} {1}.' -f $values

Dies ist nicht splatting, da ich das gesamte Array übergibt, aber die Idee ist ähnlich.

Erweiterte Formatierung

Ich habe diese absichtlich als aus .NET herausgerufen, da es bereits viele Formatierungsoptionen gibt, die bereits gut dokumentiert sind . Es gibt integrierte Methoden zum Formatieren verschiedener Datentypen.

"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f  8175133
20211110
Population 8,175,133

Ich werde nicht in sie gehen, aber ich wollte Ihnen nur mitteilen, dass dies ein sehr leistungsfähiges Formatierungsmodul ist, wenn Sie es benötigen.

Verknüpfen von Zeichenfolgen

Manchmal möchten Sie tatsächlich eine Liste von Werten miteinander verketten. Es gibt einen -join Operator, der dies für Sie tun kann. Sie können sogar ein Zeichen angeben, das zwischen den Zeichenfolgen verknüpft werden soll.

$servers = @(
    'server1'
    'server2'
    'server3'
)

$servers  -join ','

Wenn Sie einige Zeichenfolgen ohne Trennzeichen verwenden möchten -join , müssen Sie eine leere Zeichenfolge ''angeben. Aber wenn das alles ist, was Sie brauchen, gibt es eine schnellere Option.

[string]::Concat('server1','server2','server3')
[string]::Concat($servers)

Es lohnt sich auch, darauf hinzuweisen, dass Sie auch -split Zeichenfolgen verwenden können.

Join-Path

Dies wird häufig übersehen, aber ein hervorragendes Cmdlet zum Erstellen eines Dateipfads.

$folder = 'Temp'
Join-Path -Path 'C:\windows' -ChildPath $folder

Das Große daran ist, dass die umgekehrten Schrägstriche richtig funktionieren, wenn sie die Werte zusammenfügt. Dies ist besonders wichtig, wenn Sie Werte von Benutzern oder Konfigurationsdateien verwenden.

Das geht auch gut mit Split-Path und Test-Path. Ich bedecken diese auch in meinem Beitrag über das Lesen und Speichern in Dateien.

Zeichenfolgen sind Arrays

Ich muss hier das Hinzufügen von Zeichenfolgen erwähnen, bevor ich fortfahren kann. Denken Sie daran, dass eine Zeichenfolge nur ein Array von Zeichen ist. Wenn Sie mehrere Zeichenfolgen zusammen hinzufügen, wird jedes Mal ein neues Array erstellt.

Sehen Sie sich dieses Beispiel an:

$message = "Numbers: "
foreach($number in 1..10000)
{
    $message += " $number"
}

Es sieht sehr einfach aus, aber was Sie nicht sehen, ist, dass jedes Mal, wenn eine Zeichenfolge hinzugefügt $message wird, eine ganze neue Zeichenfolge erstellt wird. Der Speicher wird zugewiesen, Die Daten werden kopiert, und die alte wird verworfen. Kein großer Deal, wenn es nur ein paar Mal getan wird, aber eine Schleife wie dies würde das Problem wirklich verfügbar machen.

StringBuilder

StringBuilder ist auch sehr beliebt für das Erstellen großer Zeichenfolgen aus vielen kleineren Zeichenfolgen. Der Grund dafür ist, dass sie nur alle Zeichenfolgen sammelt, die Sie hinzufügen, und verkettet alle diese nur am Ende, wenn Sie den Wert abrufen.

$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"

[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
    [void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()

Auch hier geht es um etwas, für das ich .NET erreichen werde. Ich verwende es nicht mehr oft, aber es ist gut zu wissen, dass es da ist.

Abgrenzung mit geschweiften Klammern

Dies wird für Suffixverkettung innerhalb der Zeichenfolge verwendet. Manchmal verfügt die Variable nicht über eine klare Wortgrenze.

$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"

Vielen Dank an Redditor u/real_parbold für das eine.

Hier ist eine Alternative zu diesem Ansatz:

Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester

Ich persönlich verwende die Formatzeichenfolge dafür, aber dies ist gut zu wissen, falls Sie es in der Wildbahn sehen.

Suchen und Ersetzen von Token

Während die meisten dieser Features ihre eigene Lösung einschränken, gibt es Zeiten, in denen Sie möglicherweise umfangreiche Vorlagendateien haben, in denen Sie Zeichenfolgen ersetzen möchten.

Angenommen, Sie haben eine Vorlage aus einer Datei mit viel Text abgerufen.

$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'

Möglicherweise müssen Sie viele Token ersetzen. Der Trick besteht darin, ein sehr unterschiedliches Token zu verwenden, das leicht zu finden und zu ersetzen ist. Ich tendiere dazu, ein Sonderzeichen an beiden Enden zu verwenden, um es zu unterscheiden.

Ich habe kürzlich eine neue Möglichkeit gefunden, dies zu erreichen. Ich habe beschlossen, diesen Abschnitt hier zu verlassen, da es sich um ein Muster handelt, das häufig verwendet wird.

Ersetzen mehrerer Token

Wenn ich eine Liste von Token habe, die ich ersetzen muss, nehme ich einen allgemeineren Ansatz. Ich würde sie in eine Hashtabelle setzen und sie durchlaufen, um die Ersetzung zu erledigen.

$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
}

Diese Token können bei Bedarf aus JSON oder CSV geladen werden.

ExecutionContext ExpandString

Es gibt eine clevere Möglichkeit, eine Ersetzungszeichenfolge mit einzelnen Anführungszeichen zu definieren und die Variablen später zu erweitern. Sehen Sie sich dieses Beispiel an:

$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)

Der Aufruf für InvokeCommand.ExpandString den aktuellen Ausführungskontext verwendet die Variablen im aktuellen Bereich für die Ersetzung. Das Wichtigste ist, dass die $message Variablen sehr früh definiert werden können, bevor die Variablen sogar vorhanden sind.

Wenn wir das nur ein bisschen erweitern, können wir diese Ersetzung immer wieder mit unterschiedlichen Werten durchführen.

$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
    $ExecutionContext.InvokeCommand.ExpandString($message)
}

Um diese Idee weiter zu verfolgen; Sie könnten eine große E-Mail-Vorlage aus einer Textdatei importieren, um dies zu tun. Ich muss Mark Kraus für diesen Vorschlag danken.

Alles, was für Sie am besten funktioniert

Ich bin ein Fan des Formatzeichenfolgenansatzes. Ich tue dies definitiv mit den komplizierteren Zeichenfolgen oder wenn mehrere Variablen vorhanden sind. Auf etwas, das sehr kurz ist, kann ich eines dieser Elemente verwenden.

Irgendetwas anderes?

Ich habe hier viel Boden bedeckt. Meine Hoffnung ist, dass Sie etwas Neues lernen.

Wenn Sie mehr über die Methoden und Features erfahren möchten, die die Zeichenfolgeninterpolation ermöglichen, finden Sie in der folgenden Liste für die Referenzdokumentation.