it-swarm.com.de

Teilen Sie den String mit der PowerShell auf und machen Sie mit jedem Token etwas

Ich möchte jede Zeile einer Pipe in Leerzeichen aufteilen und dann jedes Token in einer eigenen Zeile drucken.

Mir ist klar, dass ich dieses Ergebnis erhalten kann mit:

(cat someFileInsteadOfAPipe).split(" ")

Aber ich möchte mehr Flexibilität. Ich möchte mit jedem Token so ziemlich alles machen können. (Früher habe ich AWK unter Unix verwendet, und ich versuche, dieselbe Funktionalität zu erhalten.)

Ich habe momentan:

echo "Once upon a time there were three little pigs" | %{$data = $_.split(" "); Write-Output "$($data[0]) and whatever I want to output with it"}

Was natürlich nur den ersten Token druckt. Gibt es eine Möglichkeit für mich, über die Token zu gehen, und jede nacheinander zu drucken?

Auch den %{$data = $_.split(" "); Write-Output "$($data[0])"}-Teil, den ich von einem Blog bekommen habe, und ich verstehe wirklich nicht, was ich mache oder wie die Syntax funktioniert.

Ich möchte googeln, weiß aber nicht, wie ich es nennen soll. Bitte helfen Sie mir mit einem oder zwei Wörtern an Google oder einem Link, der mir erklärt, was der % und alle $-Symbole tun, sowie die Bedeutung der öffnenden und schließenden Klammern.

Ich weiß, dass ich (cat someFileInsteadOfAPipe).split(" ") nicht wirklich verwenden kann, da die Datei (oder die bevorzugte eingehende Pipe) mehr als eine Zeile enthält.

Zu einigen Antworten:

Wenn Sie Select-String verwenden, um die Ausgabe vor der Tokenisierung zu filtern, müssen Sie beachten, dass die Ausgabe des Befehls Select-String keine Sammlung von Zeichenfolgen, sondern eine Sammlung von MatchInfo-Objekten ist. Um zu der Zeichenfolge zu gelangen, die Sie teilen möchten, müssen Sie auf die Line-Eigenschaft des MatchInfo-Objekts zugreifen, z.

cat someFile | Select-String "keywordFoo" | %{$_.Line.Split(" ")}
52
Pieter Müller
"Once upon a time there were three little pigs".Split(" ") | ForEach {
    "$_ is a token"
 }

Der Schlüssel ist $_, der für die aktuelle Variable in der Pipeline steht.

Über den Code, den Sie online gefunden haben: 

% ist ein Alias ​​für ForEach-Object . Alles, was in den Klammern eingeschlossen ist, wird für jedes empfangene Objekt einmal ausgeführt. In diesem Fall wird es nur einmal ausgeführt, da Sie eine einzelne Zeichenfolge senden. 

$_.Split(" ") nimmt die aktuelle Variable und teilt sie in Leerzeichen auf. Die aktuelle Variable ist das, was gerade von ForEach durchlaufen wird.

104
Justus Thane

Eine andere Möglichkeit, dies zu erreichen, ist eine Kombination der Antworten von Justus Thane und mklement0. Es macht keinen Sinn, es auf diese Weise zu machen, wenn Sie sich ein Beispiel mit einem Einzeiler anschauen, aber wenn Sie versuchen, eine Datei oder eine Reihe von Dateinamen in Massen zu bearbeiten, ist das sehr praktisch:

$test = '   One      for the money   '
$option = [System.StringSplitOptions]::RemoveEmptyEntries
$($test.split(' ',$option)).foreach{$_}

Dies wird wie folgt aussehen:

One
for
the
money
0
s31064

Die hilfreiche Antwort von Justus Thane ergänzen :

  • Als Joey Notes in einem Kommentar enthält PowerShell einen leistungsfähigen, auf Regex basierenden -splitOperator .

    • In seiner unary - Form (-split '...') verhält sich -split wie das Standardfeldaufteilung von [awk ", was Folgendes bedeutet:
      • Führende und nachgestellte Leerzeichen werden ignoriert.
      • Alle run von Leerzeichen (z. B. multiple benachbarte Leerzeichen) werden als single -Trennzeichen behandelt.
  • In PowerShell v4 wurde eine ausdrucksbasierte - und daher schnellere - Alternative zu ForEach-Objectcmdlet verfügbar: der .ForEach() collection "Operator" (method), wie in this beschrieben blog post (neben der .Where()-Methode eine leistungsfähigere, ausdrucksbasierte Alternative zu Where-Object).

Hier ist eine Lösung, die auf diesen Funktionen basiert:

PS> (-split '   One      for the money   ').ForEach({ "token: [$_]" })
token: [One]
token: [for]
token: [the]
token: [money]

Beachten Sie, dass der führende und der nachfolgende Leerraum ignoriert wurden und dass die mehreren Leerzeichen zwischen One und for als einzelnes Trennzeichen behandelt wurden.

0
mklement0