Ligne de commande: extraire la sous-chaîne de la sortie

25

Dis que j'exécute la commande SayStuff

$ SayStuff

et la sortie est

Watermelons and cucumbers

Maintenant. Disons que je veux extraire la sous-chaîne cucumbersde la sortie et la diriger vers quelque chose.
La façon dont je procéderais par programme serait de diviser la sortie en un tableau par le délimiteur Space et de le référencer par ArrayName[2]. Je suis assez nouveau dans les scripts shell et je n'ai réussi qu'à trouver des cutexemples semi-cryptiques , dont aucun n'avait de sens.

Des idées?

krystah
la source

Réponses:

30
$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3
cucumbers

Le -d ' 'dit cutde se diviser sur les espaces. -f 3sélectionne la troisième colonne.

Vous pouvez également utiliser awk, qui fait le fractionnement en fonction de l'espace déjà et rend les colonnes disponible $1, $2...

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
slhck
la source
Notez que cutne gérera pas un nombre variable d'espaces, alors que awkfaire.
Zitrax
13

J'utiliserais probablement l'une des options déjà données par @slhck mais voici quelques autres façons de le faire:

  1. Utilisation de tableaux, comme vous le feriez dans n'importe quelle autre langue:

    $ foo=( $(SayStuff) ) 
    $ echo ${foo[2]}
    cucumbers

    Le var=()déclare un tableau, $(command)enregistre la sortie de la commande. Donc, foo=( $(SayStuff) )stocke la sortie de SayStuffdans le tableau fooet yuou alors echoc'est le troisième élément avec ${foo[2]}.

  2. sed

    $ SayStuff | sed 's/.* \(.*\)/\1/'
    cucumbers

    La sedcommande remplacera ( s///) tout par le dernier mot. Le regex correspond à tout jusqu'à un espace ( .*) qui correspondra à tout jusqu'au dernier espace, puis capture le dernier mot (\(.*\). Puisque le mot a été capturé, nous pouvons l'appeler \1.

    Une version plus simple:

    $ SayStuff | sed 's/.* //'
    cucumbers
  3. frapper

    $ foo=$(SayStuff); echo ${foo##* } 
    cucumbers

    Cela utilise les capacités de manipulation de chaînes de bash, voir ici pour plus de détails.

  4. Plus bash

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
  5. Perl, où bien sûr, il existe de nombreuses façons de le faire:

    $ SayStuff | perl -lane 'print $F[$#F]'
    cucumber

    Les -amarques perlse comportent comme si elles awkdivisaient les lignes dans les espaces et les enregistraient dans le tableau @F. Nous imprimons ensuite le dernier élément de @F( $#Fest le nombre d'éléments dans @F). Le -ldit à perl d'ajouter une nouvelle ligne à chaque printinstruction, le -nfait qu'il doit traiter STDIN ligne par ligne et -equ'il doit exécuter le script donné sur la ligne de commande.

    $ SayStuff | perl -pe 's/.* //'
    cucumber

    Les options ont été expliquées ci-dessus, nous supprimons simplement tout jusqu'au dernier espace et imprimons ( -p).

    $ perl -le 'print $ARGV[$#ARGV]' $(SayStuff)
    cucumbers

    Ici , nous passons Watermelons and cucumberscomme arguments qui perl économiseront dans le @ARGtableau et, nous imprimer le dernier élément de @ARG.

  6. tromperie. Celui-ci utilise sedpour convertir les espaces en retours à la ligne, puis tailpour imprimer uniquement la dernière ligne.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
  7. grep et expressions régulières, -oqui n'impriment que la chaîne correspondante.

    $ SayStuff | grep -Po '\w+$' 
    cucumbers
  8. La triche

    $ SayStuff | grep -o cucumbers
    cucumbers
terdon
la source
2

Voici quelques explications supplémentaires:

Usage: cut OPTION... [FILE]...

Print selected parts of lines from each FILE to standard output.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter

   -f, --fields=LIST
          select only these fields;  also print any line that contains  no
          delimiter character, unless the -s option is specified

Donc, si vous avez besoin du 3e champ et qu'il est délimité par des espaces '', il est

$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3  
cucumbers

Si vous voulez que le DERNIER champ , vous devriez probablement utiliser awk .
Dans ce cas, cela devient:

$ echo "Pastèques et concombres" | awk '{print $ NF}'
concombres

Dans awkNF est le nombre de champs de la ligne, donc $NFle dernier champ de la ligne.

zéridon
la source
Fondamentalement, la même question est ici mais plus généralisée: stackoverflow.com/questions/3162385/… Oui, vous pouvez utiliser d'autres moyens mais awk est le plus court
zeridon