Imprimir elementos de matriz en líneas separadas en Bash?

229

¿Cómo imprimo el elemento de matriz de una matriz Bash en líneas separadas? Este funciona, pero seguramente hay una mejor manera:

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

Probé este pero no funcionó:

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

Respuestas:

436

Intenta hacer esto:

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

La diferencia entre $@y $*:

  • Sin citar, los resultados no están especificados. En Bash, ambos se expanden para separar args y luego se dividen y engloban.

  • Citado, "$@"expande cada elemento como un argumento separado, mientras que se "$*" expande a los argumentos combinados en un argumento: "$1c$2c..."(donde ces el primer carácter de IFS).

Casi siempre quieres "$@". Lo mismo vale para "${arr[@]}".

¡Cítalos siempre!

Gilles Quenot
fuente
55
Y tenga en cuenta que las comillas dobles alrededor de la referencia de la variable son importantes si desea asegurarse de que los elementos con espacios internos no se dividan inadvertidamente.
danfuzz
44
@sputnick: no funciona, los elementos de la matriz terminan en una sola línea
Axel Bregnsbo
1
¿Para qué son los dos guiones después del comando? No encontré ninguna referencia a él en el manual.
joanpau
3
¿Hay alguna manera de hacerlo para que no muestre líneas en blanco si no hay elementos en la matriz sin tener que hacerlo | grep -v '^$'?
Noel Yap
2
@espaciomore '% s \ n' es el formato para la salida de la función printf. % s significa un marcador de posición para un argumento de cadena (en este caso, el elemento de matriz) y \ n agrega un salto de línea después de eso. Por lo tanto, habrá una cadena y un salto de línea en la salida para cada elemento de la matriz.
Koja
71

Solo cita el argumento para hacer eco:

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

el sub shell ayuda a restaurar el IFS después de su uso

perreal
fuente
3
lo siento perreal, moví mi marca de verificación a sputnick, a pesar de que su solución me gustó mejor, solo porque aprendí sobre la función 'printf'.
Axel Bregnsbo
3
Gracias por esta respuesta, ¡me gusta! Las asignaciones son muy malas después de la expansión, por lo IFS=$'\n' echo "${my_array[*]}"que no funciona. ¡Oh bien!
cxw
@cxw, ¿qué quieres decir con "asignaciones suceden"?
Steven Shaw
1
@bschlueter, probé con Bash 4 - 4.4.23 (1) -release - ¡y funciona!
Steven Shaw
1
@cxw Ah, no vi lo que intentabas hacer allí. Creo que no funciona porque echoestá integrado en Bash. Sin embargo, puede envolverlo en una función y funcionará. gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw
40

Utilizando para :

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

Usando la historia ; tenga en cuenta que esto fallará si sus valores contienen !:

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

Usando basename ; tenga en cuenta que esto fallará si sus valores contienen /:

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

Usando shuf ; tenga en cuenta que los resultados pueden no aparecer en orden:

shuf -e "${alpha[@]}"
Steven Penny
fuente
19
"shuf" ... "podría no salir en orden" ... hilarante.
Walf
44
para shuf. ¿Quién hubiera pensado usar eso?
fbicknel
3

Intenté las respuestas aquí en un gigante para ... if loop, pero no tuve ninguna alegría, así que lo hice así, tal vez desordenado pero hice el trabajo:

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

aunque eso agregó un espacio a la lista, lo cual está bien, quería un poco sangrado. También suponga que "\ n" podría imprimirse en el original $ EP_LIST.

wuxmedia
fuente
55
No parece un ejemplo completo.
kenorb
3

Otra variante útil es canalizar a tr:

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

Esto se ve simple y compacto

0x00
fuente
11
Excepto que esto se rompemy_array=( "one two" three )
Mike Holt
Se corrigió con comillas dobles.
Steven Shaw
No funcionó como se anuncia en la versión Bash 4+, tuve que usarlo echo "${my_array[@]}" | tr '' ' \n', aunque personalmente evitaría usarlo echoasí, donde trcreo que algo así tr '' ' \n' <<<"${my_array[@]}"podría ser un poco más fácil de leer más tarde.
S0AndS0