web-dev-qa-db-fra.com

Fractionner une chaîne avec PowerShell et faire quelque chose avec chaque jeton

Je souhaite fractionner chaque ligne d'un tuyau sur des espaces, puis imprimer chaque jeton sur sa propre ligne.

Je réalise que je peux obtenir ce résultat en utilisant:

(cat someFileInsteadOfAPipe).split(" ")

Mais je veux plus de flexibilité. Je veux pouvoir faire à peu près n'importe quoi avec chaque jeton. (J'avais l'habitude d'utiliser AWK sur Unix, et j'essaie d'obtenir les mêmes fonctionnalités.)

J'ai actuellement:

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

Ce qui, évidemment, n'imprime que le premier jeton. Existe-t-il un moyen pour moi d’opérer chacun des jetons en les imprimant tour à tour?

En outre, la partie %{$data = $_.split(" "); Write-Output "$($data[0])"} que j'ai obtenue d'un blog et je ne comprends vraiment pas ce que je fais ou comment fonctionne la syntaxe.

Je veux google pour cela, mais je ne sais pas comment l'appeler. Aidez-moi s'il vous plaît avec un mot ou deux de Google, ou un lien m'expliquant ce que font les % et tous les symboles $, ainsi que la signification des crochets d'ouverture et de fermeture.

Je réalise que je ne peux pas réellement utiliser (cat someFileInsteadOfAPipe).split(" "), car le fichier (ou le canal entrant préférable) contient plus d'une ligne.

En ce qui concerne certaines des réponses:

Si vous utilisez Select-String pour filtrer la sortie avant la création de jetons, n'oubliez pas que la sortie de la commande Select-String n'est pas une collection de chaînes, mais une collection d'objets MatchInfo. Pour obtenir la chaîne que vous souhaitez scinder, vous devez accéder à la propriété Line de l'objet MatchInfo, comme suit:

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

La clé est $_, qui représente la variable en cours dans le pipeline.

À propos du code que vous avez trouvé en ligne: 

% est un alias pour ForEach-Object . Tout ce qui est contenu entre les crochets est exécuté une fois pour chaque objet qu’il reçoit. Dans ce cas, il ne s'exécute qu'une fois, car vous lui envoyez une seule chaîne. 

$_.Split(" ") prend la variable actuelle et la divise en espaces. La variable actuelle sera celle qui est en train d'être bouclée par ForEach.

104
Justus Thane

Une autre façon d’y parvenir est de combiner les réponses de Justus Thane et de mklement0. Cela n'a pas de sens de le faire de cette façon lorsque vous regardez un exemple avec une ligne, mais lorsque vous essayez d'éditer en masse un fichier ou plusieurs noms de fichiers, cela s'avère très pratique:

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

Cela va sortir comme:

One
for
the
money
0
s31064

Pour compléter la réponse utile de Justus Thane :

  • Comme Joey note dans un commentaire, PowerShell dispose d’un puissant -splitopérateur .

    • Dans sa forme unaire (-split '...'), -split se comporte comme le fractionnement de champ par défaut de awk}, ce qui signifie que:
      • Les espaces de début et de fin sont ignorés.
      • Tout exécution d'espaces (par exemple, plusieurs espaces adjacents) est traité comme un séparateur unique.
  • Dans PowerShell v4, une expression - et donc plus rapide - alternative au ForEach-Objectcmdlet est devenue disponible: la collection .ForEach() "opérateur" (méthode), comme décrit dans this blog post (à côté de la méthode .Where(), une alternative plus puissante que Where-Object, basée sur l’expression).

Voici une solution basée sur ces fonctionnalités:

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

Notez que les espaces de début et de fin ont été ignorés et que les multiples espaces entre One et for ont été traités comme un seul séparateur.

0
mklement0