String splitsen met PowerShell en iets doen met elk token

Ik wil elke regel van een pijp op spaties splitsen en vervolgens elk token op zijn eigen regel afdrukken.

Ik realiseer me dat ik dit resultaat kan krijgen met:

(cat someFileInsteadOfAPipe).split(" ")

Maar ik wil meer flexibiliteit. Ik wil zo ongeveer alles kunnen doen met elke token. (Ik gebruikte vroeger AWKop Unix, en ik probeer dezelfde functionaliteit te krijgen.)

Ik heb momenteel:

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

Die uiteraard alleen het eerste token afdrukt. Is er een manier waarop ik elk over de tokens kan schrijven en ze om de beurt kan afdrukken?

Ook de %{$data = $_.split(" "); Write-Output "$($data[0])"}deel dat ik van een blog heb gekregen, en ik begrijp echt niet wat ik doe of hoe de syntaxis werkt.

Ik wil ernaar googlen, maar ik weet niet hoe ik het moet noemen. Help me alsjeblieft met een paar woorden naar Google, of een link die me uitlegt wat de %en alle $-symbolen doen, evenals de betekenis van de opening en haakjes sluiten.

Ik realiseer me dat ik (cat someFileInsteadOfAPipe).split(" ")niet kan gebruiken, omdat het bestand (of bij voorkeur inkomende pijp) meer dan één regel bevat.

Over enkele van de antwoorden:

Als u Select-Stringgebruikt om de uitvoer voordat u tokeniseert, moet u er rekening mee houden dat de uitvoer van de opdracht Select-Stringgeen verzameling tekenreeksen is, maar een verzameling MatchInfo-objecten. Om bij de tekenreeks te komen die u wilt splitsen, moet u toegang krijgen tot de eigenschap Linevan het MatchInfo-object, zoals:

cat someFile | Select-String "keywordFoo" | %{$_.Line.Split(" ")}

Antwoord 1, autoriteit 100%

"Once upon a time there were three little pigs".Split(" ") | ForEach {
    "$_ is a token"
 }

De sleutel is $_, wat staat voor de huidige variabele in de pijplijn.

Over de code die je online hebt gevonden:

%is een alias voor ForEach-Object. Alles wat tussen de haakjes staat, wordt één keer uitgevoerd voor elk object dat het ontvangt. In dit geval wordt het maar één keer uitgevoerd, omdat je het een enkele string stuurt.

$_.Split(" ")neemt de huidige variabele en splitst deze op spaties. De huidige variabele is datgene wat momenteel wordt doorgelust door ForEach.


Antwoord 2, autoriteit 2%

Als aanvulling op Het nuttige antwoord van Justus Thane:

  • Zoals Joeyin een opmerking opmerkt, heeft PowerShell een krachtige, op regex gebaseerde -splitoperator.

    • In zijn unairevorm (-split '...'), gedraagt ​​-splitzich als awk‘s standaard veldsplitsing, wat betekent dat:
      • Voorloop- en volgspaties worden genegeerd.
      • Elke reekswitruimte (bijv. meerdereaangrenzende spaties) wordt behandeld als een enkelscheidingsteken.
  • In PowerShell v4+werd een op expressies gebaseerd – en dus sneller – alternatief voor de ForEach-Objectcmdletbeschikbaar: de .ForEach()array (collection) methode, zoals beschreven in deze blogpost(naast de .Where()-methode, een krachtiger, op expressies gebaseerd alternatief voor Where-Object).

Hier is een oplossing op basis van deze functies:

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

Merk op dat de voorloop- en volgspaties werden genegeerd en dat de meerdere spaties tussen Oneen forwerden behandeld als een enkel scheidingsteken.


Antwoord 3

-split voert een array uit en u kunt deze opslaan in een variabele zoals deze:

$a = -split 'Once  upon    a     time'
$a[0]
Once

Nog iets leuks, je kunt arrays aan beide kanten van een opdrachtverklaring hebben:

$a,$b,$c = -split 'Once  upon    a'
$c
a

Antwoord 4

Een andere manier om dit te bereiken is een combinatie van de antwoorden van Justus Thane en mklement0. Het heeft geen zin om het op deze manier te doen als je naar een one-liner-voorbeeld kijkt, maar als je probeert een bestand of een aantal bestandsnamen massaal te bewerken, is het best handig:

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

Dit komt eruit als:

One
for
the
money

Other episodes