Réponses:
Awk est une bonne option si vous devez gérer des espaces blancs de fin, car il s'en chargera pour vous:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Cut ne s'en chargera pas:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
«couper» ici n'imprime rien / espace, car la première chose avant un espace était un autre espace.
-F","
pour remplacer le séparateur de champ par défaut (un espace) par une virgule.
pas besoin d'utiliser des commandes externes. Bash lui-même peut faire le travail. En supposant que "mot1 mot2" vous avez obtenu de quelque part et stocké dans une variable, par exemple
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
maintenant vous pouvez assigner $ 1, ou $ 2 etc à une autre variable si vous le souhaitez.
stdin
. @Matt M. --
signifie stdin
, ainsi $string
est transmis comme stdin
. stdin
est des espaces séparés en arguments $1
, $2
, $3
, etc. - comme quand un argument de Évalue du programme Bash (chèques $1
, $2
etc.), cette approche profite de la tendance à diviser la du shell stdin
dans les arguments automatiquement, supprimant la nécessité awk
ou cut
.
set
définit les arguments du shell.
word1=$(IFS=" " ; set -- $string ; echo $1)
Réglez IFS pour reconnaître correctement l'espace entre les mots. Mettez entre parenthèses pour éviter d'écraser le contenu original de 1 $.
string="*"
. Surprise.
Je pense qu'un moyen efficace est l'utilisation de 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 lire directement les tableaux dans un pipe-line:
echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
string="*"
. Surprise.
while
syntaxe pour récupérer chaque premier mot à chaque ligne. Sinon, utilisez l'approche Boontawee Home. Veuillez également noter que cela echo "${array[0]}"
a été cité pour empêcher l'expansion comme l'a remarqué gniourf-gniourf.
echo "word1 word2 word3" | { read first rest ; echo $first ; }
Cela présente l'avantage de ne pas utiliser de commandes externes et de laisser intactes les variables $ 1, $ 2, etc.
$1, $2, …
intactes est une fonctionnalité extrêmement utile pour l'écriture de scripts!
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 à ne pas vous échapper de l'espace unique. Voir ici pour plus d'exemples de modèles de substitution. Si vous avez bash> 3.0, vous pouvez également utiliser la correspondance d'expressions régulières pour gérer les espaces de début - voir ici :
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
%% *
Voici une autre solution utilisant l' expansion des paramètres du shell . Il prend en charge plusieurs espaces après le premier mot. La gestion des espaces devant le premier mot nécessite une extension supplémentaire.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
Le %%
signifie la suppression de la plus longue correspondance possible de *
(un espace suivi d'un nombre quelconque de tout autre caractère) dans la partie de fin de string
.
Je me suis demandé comment plusieurs des meilleures réponses se mesuraient en termes de vitesse. J'ai testé ce qui suit:
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
echo "..." | { read first _ ; echo $first ; }
Je les ai mesurés avec le temps de Python dans un script Bash dans un terminal Zsh sur macOS, en utilisant une chaîne de test avec 215 mots de 5 lettres. A fait chaque mesure cinq fois (les résultats étaient tous pour 100 boucles, le meilleur de 3) et a fait la 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")
Bon travail, électeurs 👏 Les votes (au moment de la rédaction de cet article) correspondent à la vitesse des solutions!
read -a
n'est pas valide dans le tiret)
echo "word1 word2" | cut -f 1 -d " "
cut coupe le 1er champ (-f 1) d'une liste de champs délimités par la chaîne "" (-d "")
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 tuyau: premier cas: vous ne voulez que 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 tête:
printf '%s\n' " word1 word2" | { read -r first _; printf '%s\n' "$first"; }
Je travaillais avec un périphérique embarqué qui n'avait ni perl, awk ou python et je l'ai fait avec sed à la place. Il prend en charge plusieurs espaces avant le premier mot (que les solutions cut
et bash
n'ont pas géré).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
Cela a été très utile lors de la recherche ps
des ID de processus, car les autres solutions utilisant uniquement bash n'étaient pas en mesure de supprimer les premiers espaces ps
utilisés pour l'alignement.