web-dev-qa-db-fra.com

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

Dites que je lance la commande SayStuff

$ SayStuff

et la sortie est

Watermelons and cucumbers

À présent. Dites que je veux extraire la sous-chaîne cucumbers de la sortie et la canaliser dans quelque chose.
La façon dont je procéderais par programme consisterait à diviser la sortie en tableau par le délimiteur Space et à le référencer par ArrayName[2]. Je suis assez nouveau dans les scripts Shell et je n’ai réussi qu’à déterrer des exemples cut semi-cryptiques, dont aucun n’avait de sens.

Des idées?

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

Le -d ' ' indique à cut de se scinder en espaces. -f 3 sélectionne la troisième colonne.

Vous pouvez également utiliser awk, qui effectue déjà la division en fonction de l'espace et rend les colonnes disponibles en tant que $1, $2,…

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
29
slhck

J'utiliserais probablement l'une des options déjà proposées par @slhck, mais voici quelques méthodes supplémentaires:

  1. Utiliser des tableaux, comme dans n'importe quelle autre langue:

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

    var=() déclare un tableau, $(command) enregistre le résultat de la commande. Donc, foo=( $(SayStuff) ) stocke la sortie de SayStuff dans le tableau foo et vous alors echo c'est son troisième élément avec ${foo[2]}.

  2. sed

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

    La commande sed remplacera (s///) tout par le dernier mot. La regex correspond à tout ce qui va jusqu'à un espace (.*) qui correspond à tout jusqu'au dernier espace, puis capture le dernier Word (\(.*\). Puisque le mot a été capturé, on peut le nommer \1.

    Une version plus simple:

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

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

    Ceci utilise les capacités de manipulation de chaîne 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 y a plusieurs façons de le faire:

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

    Le -a fait en sorte que Perl se comporte comme awk, divisant les lignes par des espaces et sauvegardant dans le tableau @F. Nous imprimons ensuite le dernier élément de @F ($#F est le nombre d'éléments dans @F). Le -l demande à Perl d'ajouter une nouvelle ligne à chaque instruction print, le -n selon lequel il doit traiter ligne par ligne STDIN et -e selon lequel le script doit être exécuté à la ligne de commande.

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

    Les options ont été expliquées ci-dessus, nous ne faisons que supprimer tout jusqu'au dernier espace et imprimer (-p).

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

    Ici, nous passons Watermelons and cucumbers en tant qu'arguments, ce que Perl enregistrera dans le tableau @ARG. Nous imprimons donc le dernier élément de @ARG.

  6. tromperie. Celui-ci utilise sed pour convertir les espaces en nouvelles lignes, puis tail pour n’imprimer que la dernière ligne.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
    
  7. grep et expressions régulières, en utilisant -o qui affiche uniquement la chaîne correspondante.

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

    $ SayStuff | grep -o cucumbers
    cucumbers
    
12
terdon

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 3ème champ et qu'il soit délimité par des espaces '', alors il est

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

Si vous voulez le champ LAST, vous devriez probablement utiliser awk .
Dans ce cas, il devient:

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

Dans awkNF correspond au nombre de champs de la ligne, donc $NF correspond au dernier champ de la ligne.

2
zeridon