Tags: PowerShell
Das 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.
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)
Dagegen ließe der split-Operator auch die Auftrennung von Strings mit Hilfe von RegEx zu, beispielsweise wäre ein Aufruf nach diesem Muster möglich:
"Hallo Welt" -split "\s[A-Z]"
In diesem Fall würde die Zeichenkette an allen Postionen zerteilt, wo ein Großbuchstabe auf ein Whitespace folgt, in unserem Beispiel wäre das bei " W".
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 "llo" 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.
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.
Täglich Know-how für IT-Pros mit unserem Newsletter
Ähnliche Beiträge
Weitere Links
3 Kommentare
"$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?!
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.
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?