Mencetak array ke file dengan setiap elemen array di baris baru di bash

13

Saya mencoba konten array ke dalam file dengan setiap elemen array di baris baru di file.

IFS=$'\n'   
echo "${mtches[@]}" > sample1.txt 


Isi mtches adalah "qwe" dan "asd". Tetapi sample1.txtfile tersebut berisi qwe asddalam satu baris. Mengapa tidak mengambil nilai IFS ke dalam gambar?

Ashwin
sumber

Jawaban:

16

Anda harus menggunakan printfalih-alihecho :

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

Jika mtcheskosong itu masih akan menampilkan satu baris kosong. Untuk memperhitungkan itu:

{ [ "${#mtches[@]}" -eq 0 ] || printf '%s\n' "${mtches[@]}"; } > file

Dalam bash(dan juga kerang POSIX), Anda sering menggunakan array Parameter Posisi sebagai "$@"pengganti "$*", kecuali Anda memiliki alasan khusus. Itu juga berlaku di shell yang mendukung array reguler, dari man bash - section Arrays :

Elemen array dapat dirujuk menggunakan $ {name [subscript]}. Kawat gigi diperlukan untuk menghindari konflik dengan operator ekspansi nama file shell. Jika subskripnya adalah '@' atau '*', kata tersebut diperluas ke semua anggota nama array. Subskrip ini berbeda hanya ketika kata itu muncul dalam tanda kutip ganda. Jika kata tersebut dikutip dua kali lipat, $ {name [*]} berkembang menjadi satu kata dengan nilai setiap anggota array dipisahkan oleh karakter pertama variabel IFS, dan $ {name [@]} memperluas setiap elemen nama ke kata yang terpisah. Ketika tidak ada anggota array, $ {name [@]} berkembang menjadi nol. Jika ekspansi kuotasi ganda terjadi dalam sebuah kata, ekspansi parameter pertama bergabung dengan bagian awal kata asli, dan perluasan parameter terakhir digabungkan dengan bagian terakhir dari kata asli.

Hanya gunakan "${array[*]}"saat Anda ingin menggabungkan semua elemen array ke string.

cuonglm
sumber
Bagaimana itu membuat perbedaan?
Ashwin
7

Anda ingin menggunakan ${mtches[*]}sebagai gantinya.

Saat Anda menggunakan "${mtches[@]}", tidak peduli berapa nilainya $IFS, bash akan membagi array menjadi beberapa argumen. Yang Anda inginkan adalah argumen tunggal dengan setiap elemen array bergabung \n. ${mtches[*]}menyelesaikan ini.

Juga sebagai cara pengaturan sementara $IFS, Anda dapat melakukan:

( IFS=$'\n'; echo "${mtches[*]}" > sample1.txt )

Maka Anda tidak perlu repot-repot mengaturnya kembali.

Patrick
sumber
pubs.opengroup.org/onlinepubs/9699919799/utilities/... <- Referensi POSIX (ini tidak hanya berlaku untuk bash).
Mat
Atau gunakan printf...
jasonwryan
2

Menggunakan untuk :

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

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

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

Menggunakan nama bas ; perhatikan ini akan gagal jika nilai Anda mengandung /:

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

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

shuf -e "${alpha[@]}"
Steven Penny
sumber
1
for ENTRY in ${ARRAY[@]}; do
    echo $ENTRY
done > outfile

Bagus dan mudah dibaca dan tidak berarti mengacaukan IFS. Ini juga berarti Anda dapat menyesuaikan penanganan setiap baris.

steveayre
sumber
1
Tapi salah karena Anda menggunakan echoyang tidak dapat digunakan untuk konten sewenang-wenang dan lupa mengutip variabel Anda . Versi yang sedikit lebih baik sudah diposting oleh StevenPenny
Stéphane Chazelas