web-dev-qa-db-fra.com

Comment récupérer le premier mot de la sortie d'une commande dans bash?

J'ai une commande, par exemple: echo "Word1 Word2". Je veux mettre un tuyau (|) et obtenir Word1 à partir de la commande.

echo "Word1 Word2" | ....

Je ne sais pas quoi mettre après le tuyau.

90
Neuquino

Awk est une bonne option si vous devez gérer les espaces de fuite, car ils s’occuperont de cela pour vous:

echo "   Word1  Word2 " | awk '{print $1;}' # Prints "Word1"

Cut ne prendra pas soin de cela cependant:

echo "  Word1  Word2 " | cut -f 1 -d " " # Prints nothing/whitespace

'couper' ici n'imprime rien/espace, parce que la première chose avant un espace était un autre espace.

157
mattbh

pas besoin d'utiliser des commandes externes. Bash peut faire le travail. En supposant que "Word1 Word2" vienne de quelque part et qu'il soit stocké dans une variable, par exemple

$ string="Word1 Word2"
$ set -- $string
$ echo $1
Word1
$ echo $2
Word2

vous pouvez maintenant affecter $ 1, ou $ 2, etc. à une autre variable si vous le souhaitez. 

62
ghostdog74

Je pense qu'un moyen efficace est d'utiliser des tableaux bash: 

array=( $string ) # do not use quotes in order to allow Word expansion
echo ${array[0]}  # You can retrieve any Word. Index runs from 0 to length-1

En outre, vous pouvez directement lire des tableaux dans un pipeline:

echo "Word1 Word2" | while read -a array; do echo "${array[0]}" ; done
26
Isaías
echo "Word1 Word2 Word3" | { read first rest ; echo $first ; }

Cela a l'avantage de ne pas utiliser de commandes externes et de laisser les variables $ 1, $ 2, etc.

16
John Marter

Si vous êtes sûr qu'il n'y a pas d'espaces de début, vous pouvez utiliser la substitution de paramètre bash:

$ string="Word1  Word2"
$ echo ${string/%\ */}
Word1

Attention à échapper à l'espace unique. Voir ici pour plus d’exemples de schémas de substitution. Si vous avez bash> 3.0, vous pouvez également utiliser la correspondance d’expression régulière pour faire face aux espaces principaux - voir ici :

$ string="  Word1   Word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
Word1
12
dsl101

Vous pourriez essayer awk

echo "Word1 Word2" | awk '{ print $1 }'

Avec awk, il est très facile de choisir le mot que vous aimez (1 $, 2 $, ...) 

11
mfloryan

Utilisation de l'expansion des paramètres du shell

Voici une autre solution utilisant Développement des paramètres du shell . Il prend en charge plusieurs espaces après le premier mot. La gestion des espaces devant le premier Word nécessite une extension supplémentaire.

string='Word1    Word2  '
echo ${string%% *}
Word1

Explication

Le %% signifie la suppression de la correspondance la plus longue de * (un espace suivi d'un nombre quelconque de caractères), en partant du côté droit de la variable string.

4
Serge Stroobandt
echo "Word1 Word2" | cut -f 1 -d " "

cut coupe le 1er champ (-f 1) dans une liste de champs délimités par la chaîne "" (-d "")

4
lajuette

read est votre ami:

  • Si la chaîne est dans une variable:

    string="Word1 Word2"
    read -r first _ <<< "$string"
    printf '%s\n' "$first"
    
  • Si vous travaillez dans un pipe: premier cas: vous voulez seulement le premier mot de la première ligne:

    printf '%s\n' "Word1 Word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
    

    deuxième cas: vous voulez le premier mot de chaque ligne:

    printf '%s\n' "Word1 Word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
    

Ceux-ci fonctionnent s'il y a des espaces de début:

printf '%s\n' "   Word1 Word2" | { read -r first _; printf '%s\n' "$first"; }
3
gniourf_gniourf

Je me demandais comment plusieurs des meilleures réponses se mesuraient en termes de rapidité. J'ai testé les éléments suivants:

1 @ mattbh's

echo "..." | awk '{print $1;}'

2 @ ghostdog74's

string="..."; set -- $string; echo $1

3 @ boontawee-home's

echo "..." | { read -a array ; echo ${array[0]} ; }

et 4 @ boontawee-home's

echo "..." | { read first _ ; echo $first ; }

Je les ai mesurées avec le temps de Python dans un script Bash dans un terminal Zsh sous macOS, en utilisant une chaîne de test contenant 215 mots de 5 lettres. Chaque mesure a-t-elle été effectuée cinq fois (les résultats concernaient tous 100 boucles, le meilleur des trois) et une moyenne des résultats:

method       time
--------------------------------
1. awk       9.2ms
2. set       11.6ms (1.26 * "1")
3. read -a   11.7ms (1.27 * "1")
4. read      13.6ms (1.48 * "1")

Beau travail, électeurs ???? Les votes (au moment d'écrire ces lignes) correspondent à la vitesse des solutions!

3
henry

Je travaillais avec un périphérique intégré qui ne contenait ni Perl, awk ou python et le faisait avec sed. Il prend en charge plusieurs espaces avant le premier mot (que les solutions cut et bash n'ont pas gérées).

VARIABLE="  first_Word_with_spaces_before_and_after  another_Word  "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'

Cela était très utile lorsque grepping ps pour les ID de processus, car les autres solutions utilisant uniquement bash ne pouvaient pas supprimer les premiers espaces que ps utilisait pour s'aligner.

0
Johan Bjäreholt

Comme Perl intègre les fonctionnalités d'awk, cela peut également être résolu avec Perl:

echo " Word1 Word2" | Perl -lane 'print $F[0]'
0
tssch