Strings in PowerShell: Ersetzen, Vergleichen, Zusammenfügen, Split, Substring


    Tags:

    String-Manipulation in PowerShellDas Bearbeiten von Strings gehört zu den häufigsten Operationen in Script-Sprachen. Während althergebrachte Tools wie Batch-Dateien und VBScript solche Aufgaben oft nur umständlich bewältigen können, bietet PowerShell das ganze Inventar an Funktionen, die man etwa von Javascript oder PHP kennt.

    Wesentlich zum Verständnis von String-Manipulationen in PowerShell ist die Tatsache, dass es sich bei Zeichenketten immer um Objekte handelt - und zwar unabhängig davon, ob sie wörtlich oder als Variablen vorliegen. Daher stellen die Methoden der String-Objekte die meisten benötigten Funktionen zur Verfügung. Diese kann man wie gewohnt durch das Cmdlet Get-Member anzeigen lassen:

    "Hallo Welt" | Get-Member

    Das Ergebnis besteht aus einer beachtlichen Liste:

    Clone CompareTo Contains CopyTo EndsWith
    Equals GetEnumerator GetHashCode GetType GetTypeCode
    IndexOf IndexOfAny Insert IsNormalized LastIndexOf
    LastIndexOfAny Normalize PadLeft PadRight Remove
    Replace Split StartsWith Substring ToBoolean
    ToByte ToChar ToCharArray ToDateTime ToDecimal
    ToDouble ToInt16 ToInt32 ToInt64 ToLower
    ToLowerInvariant ToSByte ToSingle ToString ToType
    ToUInt16 ToUInt32 ToUInt64 ToUpper ToUpperInvariant
    Trim TrimEnd TrimStart    

    Zeichenketten zusammenfügen

    Einige Aufgaben erfordern darüber hinaus jedoch den Einsatz von Operatoren. Dazu zählt mangels einer concat-Funktion etwa das Verketten von Strings, was die Sache aber letztlich einfacher macht. So kann man zwei oder mehrere Zeichenketten schlicht mit dem Plus-Operator zusammenfügen:

    $h = "Hallo"
    $w = "Welt"
    $h + " " + $w

    Alternativ kann man einfach die beiden Strings innerhalb von Anführungszeichen expandieren:

    "$h $w"

    Das Leerzeichen in diesem Beispiel gewährleistet, dass die beiden Wörter nicht zusammenkleben. Man könnte stattdessen ein beliebiges anderes Trennzeichen einsetzen.

    Strings lassen sich in PowerShell verketten, ohne dass man dafür eine concat-Funktion benötigt.

    Dieses Verfahren eignet sich auch, um die Elemente eines String-Arrays zu konkatenieren:

    $st = @("Hallo Welt", "Hello World")

    "$st"

    In diesem Fall fügt PowerShell automatisch ein Leerzeichen zwischen die verketteten Elemente des Arrays ein.

    Als weitere Option für das Zusammenfügen von Zeichenketten bietet sich der join-Operator an, dessen Verwendung aber nicht gerade intuitiv ist. So steht er normal vor den Strings, außer man möchte diese nach dem Verschmelzen durch einen Separator trennen:

    -join($h,$w)

    Ist man in diesem Beispiel nicht mit dem Ergebnis "HalloWelt" einverstanden und möchte ein Leerzeichen zwischen den beiden Wörtern, dann erfolgt der Aufruf in dieser Form:

    $h,$w -join " "

    Strings zerlegen

    Für den umgekehrten Vorgang, nämlich das Auftrennen von Zeichenketten, hat man die Wahl zwischen der Split-Methode und dem split-Operator. Erstere ist einfacher gestrickt und erlaubt nur die Verwendung von expliziten Separatoren, während der Operator auch reguläre Ausdrücke zulässt (siehe dazu: Regex in PowerShell verwenden).

    So würde

    ("Hallo Welt").split("l ")

    die Zeichenkette am 'l' und am Leerzeichen zerteilen, wobei die Trennzeichen dabei auf der Strecke bleiben. Das Ergebnis liegt als Array vor, wobei man mit Hilfe eines weiteren Parameters von Split festlegen kann, in wie viele Elemente der String maximal zerlegt wird. Hier wären es 2:

    ("Hallo Welt").split("l ", 2)

    Substring extrahieren

    Einem ähnlichen Anliegen wie Split dient die Methode Substring, weil sie einen Teil der Zeichenkette herauslösen kann. Dies erfolgt aber nicht anhand von Trennzeichen, sondern wie in anderen Sprachen über Positionsangaben:

    ("Hallo Welt").Substring(2,5)

    Dieser Aufruf ergibt die Zeichenkette "llo W", also den Abschnitt beginnend beim 3. Zeichen (die Zählung beginnt bei 0!) und einer Länge von 5.

    Lässt man den Wert für die Länge des Substrings weg (in diesem Beispiel also die 5), dann liefert die Funktion einfach die gesamte Zeichenkette ab der Position x:

    ("Hallo Welt").Substring(2)

    In diesem Fall wird "Hallo Welt" vor dem ersten 'l' abgeschnitten.

    Will man einen Teil der Zeichenkette nicht ab einer festen Position, sondern ab dem Vorkommen eines bestimmten Zeichens extrahieren, dann kombiniert man Substring mit IndexOf bzw LastIndexOf, um das letzte Auftreten eines Zeichens oder einer Zeichenkette zu berechnen:

    $x = "Das ist ein Test".LastIndexOf("ein")
    "Das ist ein Test".Substring($x)

    Zu bedenken ist hier, dass der String, dessen Position mit LastIndexOf ermittelt wird, in der Ausgabe von Substring enthalten ist. Im obigen Beispiel wäre das "ein".

    Die komplementäre Methode zu Substring ist Remove. Sie erzeugt einen Ausschnitt von Zeichenketten, indem sie den angegebenen Bereich entfernt:

    ("Hallo Welt").Remove(2,3)

    In diesem Beispiel würde "all" aus "Hallo Welt" gelöscht.

    Möchte man führende und/oder abschließende Leerzeichen eliminieren, dann kann man das mit TrimStart, TrimEnd oder Trim tun.

    Zeichen suchen und ersetzen

    PowerShell kennt eine ganze Reihe von Techniken, um Zeichen oder Substrings zu finden und zu ersetzen. Auch hier stehen für anspruchsvollere Aufgabe reguläre Ausdrücke zur Verfügung, die sich zusammen mit den Operatoren -match oder -replace einsetzen lassen. Auch hierzu nochmals der Hinweis auf meinen Beitrag zu RegEx in PowerShell.

    Die Replace-Methode akzeptiert im Gegensatz zum gleichnamigen Operator keine RegEx. Das Gleiche gilt für Contains vs. -match.

    Darüber hinaus eignen sich gleich mehrere Methoden des String-Objekts für diese Aufgabe, wobei natürlich jede von ihnen einem etwas anderen Zweck dient. So handelt es sich bei replace() um die simplere Variante zum Operator, die keine regulären Ausdrücke zulässt:

    ("Hallo Welt").Replace("Hallo","Neue")

    Ein gleichnamiges Gegenstück zu -match existiert nicht, dafür bietet PowerShell gleich mehrere Methoden, die sich auf bestimmte Formen der Suche spezialisieren. So ermitteln etwa StartsWith und EndsWith, ob eine Zeichenkette mit einem bestimmten Zeichen oder String beginnt bzw. endet. Contains wiederum gibt Aufschluss darüber, ob sie eine bestimmte Zeichenfolge enthält:

    ("Hallo Welt").Contains("ll")

    liefert als Ergebnis den Wert TRUE. Um die Position eines Zeichens oder Substrings zu ermitteln, steht IndexOf zur Verfügung:

    ("Hallo Welt").IndexOf("ll")

    Auch hier ist daran zu denken, dass die Zählung für das erste Zeichen bei 0 beginnt.

    Zeichenketten vergleichen

    Grundsätzlich lassen sich Unterschiede zwischen Strings über jene Vergleichsoperatoren ermitteln, die auch für nummerische Werte verwendet werden. Dazu zählen primär -eq und -ne. Hinzu kommt -like, das Wildcards akzeptiert.

    Nicht genug damit, String-Objekte bieten auch dafür noch eigene Methoden an. Es handelt sich dabei um CompareTo und um Equals. Ersteres gibt den Wert 1 zurück, wenn die erste Zeichenkette in der Sortierreihenfolge zuerst kommt, und -1, wenn es umgekehrt ist. Bei Gleichheit liefert es 0, so dass CompareTo ohne weiteres die Methode Equals ersetzen kann:

    ("Hallo Welt").CompareTo($h + " " + $w)

    Nachdem $h den Wert "Hallo" und $w "Welt" enthält, ist das Ergebnis in diesem Beispiel 0. Der äquivalente Aufruf von Equals mit

    ("Hallo Welt").Equals($h + " " + $w)

    ergibt dagegen TRUE.

    3 Kommentare

    Bild von MOD
    MOD sagt:
    17. Februar 2016 - 13:55

    "$h $w"

    Das Leerzeichen in diesem Beispiel gewährleistet, dass die beiden Wörter nicht zusammenkleben. Man könnte stattdessen ein beliebiges anderes Trennzeichen einsetzen.

    Leider funktioniert das nicht mit jedem Zeichen?!
    "$h_$w" geht nicht?!

    Bild von Wolfgang Sommergut
    17. Februar 2016 - 21:29

    Der Unterstrich gilt nicht als Trennzeichen. Als solche kann man neben dem Leerzeichen auch Interpunktionszeichen wie ;:., verwenden, auch der Bindestrich gilt. Beim _ kann man die Strings durch
    $h + "_" + $w
    expandieren.

    Bild von uwe
    uwe sagt:
    4. April 2016 - 13:52

    Hallo,
    ich habe folgende Eintraege in einer Datei:
    clihome=D:\N4Auto\de.hhla.itleitstand.cli-1.0.0
    jar=$clihome\de.hhla.itleitstand.cli.jar

    diese Datei lese ich mit dem folgenden code aus und möchte daraus variablen erzeugen und denen werte zuweisen:

    function loadInstanzProperties
    {
    $scripthome = Get-Location
    $properties = "$scripthome/config/instanz.properties"
    $input = Get-Content $properties

    foreach ($temp in $input)
    {
    $Inhalttrennen = $temp.Split("=")
    if ($Inhalttrennen[0] -notlike "#*")
    {
    $attribut = $Inhalttrennen[0]
    $wert = -join $Inhalttrennen[1]

    if ($attribut)
    {
    new-variable -scope "1" -name $attribut -value "$wert"

    $Ausgabe = "$attribut $wert"
    $Ausgabe
    }
    }
    }
    }

    funktioniert soweit ganz gut, nur:
    der wert der erzeugten variablen clihome ist D:\N4Auto\de.hhla.itleitstand.cli-1.0.0 => ok
    Aber: jar wird $clihome\de.hhla.itleitstand.cli.jar und loest sich nicht nach D:\N4Auto\de.hhla.itleitstand.cli-1.0.0\de.hhla.itleitstand.cli.jar auf.
    d.h. das $clihome wird nicht aufgeloest.
    ich bin ratlos, kann wer helfen?