Imprimir elementos da matriz em linhas separadas no Bash?

229

Como imprimo o elemento da matriz Bash em linhas separadas? Este funciona, mas certamente existe uma maneira melhor:

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

Tentei este, mas não funcionou:

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

Respostas:

436

Tente fazer isso:

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

A diferença entre $@e $*:

  • Sem aspas, os resultados não são especificados. No Bash, os dois se expandem para separar argumentos e, em seguida, dividem-se em palavras e em globos.

  • Citado, "$@"expande cada elemento como um argumento separado, enquanto se "$*" expande para os argumentos mesclados em um argumento: "$1c$2c..."(onde cé o primeiro caractere de IFS).

Você quase sempre quer "$@". O mesmo vale para "${arr[@]}".

Sempre cite-os!

Gilles Quenot
fonte
5
E observe que as aspas duplas em torno da referência da variável são importantes se você deseja garantir que os elementos com espaços internos não sejam inadvertidamente divididos.
Danfuzz 28/03
4
@sputnick: não trabalho, os elementos da matriz acabar em uma única linha
Axel Bregnsbo
1
Para que servem os dois hífens após o comando? Não encontrei nenhuma referência a ele no manual.
joanpau
3
Existe uma maneira de fazê-lo para que ele não produza linhas em branco se não houver elementos na matriz sem a necessidade | grep -v '^$'?
Noel Yap
2
@espaciomore '% s \ n' é o formato para a saída da função printf. % s significa um espaço reservado para um argumento de string (neste caso, o elemento da matriz) e \ n adiciona uma quebra de linha depois disso. Assim, haverá uma string e uma quebra de linha na saída para cada elemento na matriz.
Koja
71

Apenas cite o argumento para ecoar:

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

o sub shell ajuda a restaurar o IFS após o uso

perreal
fonte
3
desculpe perreal, mudei minha marca de seleção para sputnick, apesar de gostar mais de sua solução, só porque aprendi sobre a função 'printf'.
Axel Bregnsbo
3
Obrigado por esta resposta - eu gosto! Atribuições muito ruins acontecem após a expansão, portanto IFS=$'\n' echo "${my_array[*]}"não funcionam. Ah bem!
Cxw
@cxw, o que você quer dizer com "atribuições acontecem"?
22818 Steven Shaw
1
@bschlueter, tentei com o Bash 4 - 4.4.23 (1) -release - e funciona!
Steven Shaw
1
@cxw Ah, eu não vi o que você estava tentando fazer lá. Eu acho que não funciona porque echoé um builtin no Bash. No entanto, você pode envolvê-lo em uma função e ele funcionará! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw
40

Usando para :

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

Usando a história ; observe que isso falhará se seus valores contiverem !:

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

Usando o basename ; observe que isso falhará se seus valores contiverem /:

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

Usando shuf ; observe que os resultados podem não sair em ordem:

shuf -e "${alpha[@]}"
Steven Penny
fonte
19
"shuf" ... "pode ​​não sair em ordem" ... hilário.
Walf
4
para shuf. Quem teria pensado em usar isso?
Fbicknel 22/03/19
3

Eu tentei as respostas aqui em um gigante para ... if loop, mas não tive nenhuma alegria - então eu fiz assim, talvez confuso, mas fiz o trabalho:

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

embora isso tenha acrescentado um espaço à lista, o que é bom - eu queria um pouco de recuo. Suponha também que "\ n" possa ser impresso no $ EP_LIST original.

wuxmedia
fonte
5
Não parece um exemplo completo.
kenorb
3

Outra variante útil é o pipe para tr:

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

Parece simples e compacto

0x00
fonte
11
Exceto que isso aconteça #my_array=( "one two" three )
Mike Holt
Corrigido com aspas duplas.
Steven Shaw
Não funcionou como anunciado na versão 4+ do Bash , tinha que usar echo "${my_array[@]}" | tr '' ' \n', embora pessoalmente eu evitasse usar echoassim, onde trminha escolha acho que algo como tr '' ' \n' <<<"${my_array[@]}"pode ser um pouco mais fácil de ler mais tarde.
precisa saber é o seguinte