Cetak elemen array pada baris terpisah di Bash?

238

Bagaimana cara mencetak elemen array dari array Bash pada baris terpisah? Yang ini berhasil, tapi pasti ada cara yang lebih baik:

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

Sudah mencoba yang ini tetapi tidak berhasil:

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

Jawaban:

458

Coba lakukan ini:

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

Perbedaan antara $@dan $*:

  • Tanpa kutipan, hasilnya tidak ditentukan. Di Bash, keduanya diperluas menjadi args yang terpisah dan kemudian wordsplit dan globbed.

  • Dikutip, "$@"memperluas setiap elemen sebagai argumen terpisah, sementara "$*" memperluas argumen yang digabungkan menjadi satu argumen: "$1c$2c..."(di mana ckarakter pertama IFS).

Anda hampir selalu menginginkannya "$@". Hal yang sama berlaku untuk "${arr[@]}".

Selalu kutip mereka!

Gilles Quenot
sumber
5
Dan perhatikan, tanda kutip ganda di sekitar referensi variabel penting jika Anda ingin memastikan elemen dengan spasi internal tidak terpecah secara tidak sengaja.
danfuzz
4
@sputnick: tidak berfungsi, elemen array berakhir pada satu baris
Axel Bregnsbo
1
Untuk apa dua tanda hubung setelah perintah? Saya tidak menemukan referensi untuk itu di manual.
joanpau
3
Apakah ada cara untuk membuatnya sehingga tidak menghasilkan baris kosong jika tidak ada elemen dalam array tanpa harus melakukannya | grep -v '^$'?
Noel Yap
2
@espaciomore '% s \ n' adalah format untuk keluaran fungsi printf. % s berarti tempat penampung untuk argumen string (dalam hal ini elemen array) dan \ n menambahkan jeda baris setelah itu. Dengan demikian, akan ada string dan jeda baris pada keluaran untuk setiap elemen dalam larik.
Koja
73

Kutip saja argumen untuk menggema:

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

sub shell membantu memulihkan IFS setelah digunakan

nyata
sumber
3
maaf nyata, saya memindahkan tanda centang saya ke sputnick, meskipun lebih menyukai solusi Anda, hanya karena saya belajar tentang fungsi 'printf'.
Axel Bregnsbo
3
Terima kasih atas jawaban ini - saya menyukainya! Penugasan yang terlalu buruk terjadi setelah perluasan jadi IFS=$'\n' echo "${my_array[*]}"tidak berhasil. Baiklah!
cxw
@cxw, apa yang Anda maksud dengan "penugasan terjadi"?
Steven Shaw
1
@bschlueter, saya mencoba dengan Bash 4 - 4.4.23 (1) -release - dan berhasil!
Steven Shaw
1
@cxw Ah, saya tidak melihat apa yang Anda coba lakukan di sana. Saya pikir itu tidak berfungsi karena echoada bawaan di Bash. Namun, Anda dapat membungkusnya dalam sebuah fungsi dan itu akan berhasil! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw
44

Menggunakan untuk :

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

Menggunakan sejarah ; perhatikan ini akan gagal jika nilai Anda berisi !:

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

Menggunakan nama dasar ; perhatikan ini akan gagal jika nilai Anda berisi /:

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

Menggunakan shuf ; perhatikan bahwa hasil mungkin tidak keluar secara berurutan:

shuf -e "${alpha[@]}"
Steven Penny
sumber
22
"shuf" ... "mungkin tidak keluar secara berurutan" ... lucu.
Walf
4
untuk shuf. Siapa yang mengira menggunakan itu?
fbicknel
3

Saya mencoba jawaban di sini dengan sangat besar untuk ... if loop, tetapi tidak mendapatkan kegembiraan - jadi saya melakukannya seperti ini, mungkin berantakan tetapi berhasil:

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

meskipun itu menambahkan ruang ke daftar, yang bagus - saya ingin itu sedikit menjorok ke dalam. Juga anggap "\ n" bisa dicetak dalam $ EP_LIST asli.

wuxmedia
sumber
5
Tidak terlihat seperti contoh lengkap.
kenorb
3

Varian berguna lainnya adalah pipa ke tr:

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

Ini terlihat sederhana dan kompak

0x00
sumber
11
Kecuali kerusakan ini padamy_array=( "one two" three )
Mike Holt
Perbaiki dengan tanda kutip ganda.
Steven Shaw
Tidak berfungsi seperti yang diiklankan pada Bash versi 4+, harus menggunakan echo "${my_array[@]}" | tr '' ' \n', meskipun secara pribadi saya akan menghindari penggunaan echoseperti itu, di mana trpilihan saya, saya pikir sesuatu seperti tr '' ' \n' <<<"${my_array[@]}"mungkin sedikit lebih mudah dibaca nanti.
S0AndS0