Imprimer les éléments du tableau sur des lignes distinctes dans Bash?

229

Comment imprimer l'élément de tableau d'un tableau Bash sur des lignes distinctes? Celui-ci fonctionne, mais il y a sûrement une meilleure façon:

$ my_array=(one two three)
$ for i in ${my_array[@]}; do echo $i; done
one
two
three

J'ai essayé celui-ci mais cela n'a pas fonctionné:

$ IFS=$'\n' echo ${my_array[*]}
one two three
Axel Bregnsbo
la source

Réponses:

436

Essayez de faire ceci:

$ printf '%s\n' "${my_array[@]}"

La différence entre $@et $*:

  • Non cité, les résultats ne sont pas précisés. Dans Bash, les deux se développent pour séparer les arguments, puis les mots sont séparés et globés.

  • Citée, "$@"développe chaque élément en tant qu'argument distinct, tandis que "$*" développe les arguments fusionnés en un seul argument: "$1c$2c..."(où cest le premier caractère de IFS).

Vous en avez presque toujours envie "$@". Il en va de même "${arr[@]}".

Citez-les toujours!

Gilles Quenot
la source
5
Et notez que les guillemets doubles autour de la référence de variable sont importants si vous voulez vous assurer que les éléments avec des espaces internes ne sont pas divisés par inadvertance.
danfuzz
4
@sputnick: ne fonctionne pas, les éléments du tableau se retrouvent sur une seule ligne
Axel Bregnsbo
1
À quoi servent les deux tirets après la commande? Je n'y ai trouvé aucune référence dans le manuel.
joanpau
3
Existe-t-il un moyen de faire en sorte qu'il ne génère aucune ligne vierge s'il n'y a aucun élément dans le tableau sans avoir à le faire | grep -v '^$'?
Noel Yap
2
@espaciomore '% s \ n' est le format de sortie de la fonction printf. % s signifie un espace réservé pour un argument de chaîne (dans ce cas, l'élément de tableau) et \ n ajoute un saut de ligne après cela. Ainsi, il y aura une chaîne et un saut de ligne dans la sortie pour chaque élément du tableau.
Koja
71

Citez simplement l'argument pour faire écho:

( IFS=$'\n'; echo "${my_array[*]}" )

le sous-shell aide à restaurer l'IFS après utilisation

perreal
la source
3
désolé, j'ai déplacé ma coche sur sputnick, bien que j'aimais mieux votre solution, juste parce que j'ai appris la fonction 'printf'.
Axel Bregnsbo
3
Merci pour cette réponse - j'aime ça! Dommage que les affectations se produisent après l'expansion, IFS=$'\n' echo "${my_array[*]}"cela ne fonctionne donc pas. Tant pis!
cxw
@cxw, qu'entendez-vous par «affectations»?
Steven Shaw
1
@bschlueter, j'ai essayé avec Bash 4 - 4.4.23 (1) -release - et ça marche!
Steven Shaw
1
@cxw Ah, je n'ai pas vu ce que tu essayais de faire là-bas. Je pense que cela ne fonctionne pas, car il echoest intégré à Bash. Cependant, vous pouvez l'envelopper dans une fonction et cela fonctionnera! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw
40

Utilisation pour :

for each in "${alpha[@]}"
do
  echo "$each"
done

Utiliser l' histoire ; notez que cela échouera si vos valeurs contiennent !:

history -p "${alpha[@]}"

Utilisation du nom de base ; notez que cela échouera si vos valeurs contiennent /:

basename -a "${alpha[@]}"

Utilisation de shuf ; notez que les résultats peuvent ne pas sortir dans l'ordre:

shuf -e "${alpha[@]}"
Steven Penny
la source
19
"shuf" ... "pourrait ne pas sortir dans l'ordre" ... hilarant.
Walf
4
pour shuf. Qui aurait pensé utiliser ça?
fbicknel
3

J'ai essayé les réponses ici dans un géant pour ... si boucle, mais je n'ai pas eu de joie - alors je l'ai fait comme ça, peut-être malpropre mais j'ai fait le travail:

 # EXP_LIST2 is iterated    
 # imagine a for loop
     EXP_LIST="List item"    
     EXP_LIST2="$EXP_LIST2 \n $EXP_LIST"
 done 
 echo -e $EXP_LIST2

même si cela a ajouté un espace à la liste, ce qui est bien - je le voulais un peu en retrait. Supposons également que le "\ n" puisse être imprimé dans l'original $ EP_LIST.

wuxmedia
la source
5
Ne ressemble pas à un exemple complet.
kenorb
3

Une autre variante utile est de diriger vers tr:

echo "${my_array[@]}" | tr ' ' '\n'

Cela semble simple et compact

0x00
la source
11
Sauf que cela se brisemy_array=( "one two" three )
Mike Holt
Fixé avec des guillemets doubles.
Steven Shaw
Ne fonctionnait pas comme annoncé sur la version Bash 4+, a dû utiliser echo "${my_array[@]}" | tr '' ' \n', bien que personnellement j'éviterais d'utiliser echocomme ça, où trmon choix, je pense que quelque chose comme tr '' ' \n' <<<"${my_array[@]}"pourrait être un peu plus facile à lire plus tard.
S0AndS0