Saya memiliki variabel yang berisi output multiline dari suatu perintah. Apa cara paling efisien untuk membaca output baris demi baris dari variabel?
Sebagai contoh:
jobs="$(jobs)"
if [ "$jobs" ]; then
# read lines from $jobs
fi
Anda dapat menggunakan loop sementara dengan substitusi proses:
while read -r line
do
echo "$line"
done < <(jobs)
Cara optimal untuk membaca variabel multiline adalah dengan menetapkan IFS
variabel kosong dan printf
variabel dengan baris baru:
# Printf '%s\n' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
while IFS= read -r line
do
echo "$line"
done < <(printf '%s\n' "$var")
Catatan: Sesuai shellcheck sc2031 , penggunaan subtitusi proses lebih disukai daripada pipa untuk menghindari [secara halus] membuat subkulit.
Juga, harap menyadari bahwa dengan memberi nama variabel jobs
itu dapat menyebabkan kebingungan karena itu juga nama perintah shell umum.
while IFS= read
.... Jika Anda ingin mencegah \ interpretasi, maka gunakanread -r
echo
menjadiprintf %s
, sehingga skrip Anda akan berfungsi bahkan dengan input yang tidak jinak./tmp
direktori dapat ditulis, karena ini bergantung pada kemampuan untuk membuat file kerja sementara. Jika Anda menemukan diri Anda pada sistem terbatas dengan/tmp
hanya-baca (dan tidak dapat diubah oleh Anda), Anda akan senang tentang kemungkinan menggunakan solusi alternatif, misalnya denganprintf
pipa.printf "%s\n" "$var" | while IFS= read -r line
Untuk memproses output baris perintah demi baris ( penjelasan ):
Jika Anda sudah memiliki data dalam variabel:
printf %s "$foo"
hampir identik denganecho "$foo"
, tetapi dicetak$foo
secara harfiah, sedangkanecho "$foo"
mungkin mengartikan$foo
sebagai opsi untuk perintah gema jika dimulai dengan-
, dan mungkin memperluas urutan backslash di$foo
dalam beberapa shell.Perhatikan bahwa dalam beberapa shell (abu, bash, pdksh, tetapi bukan ksh atau zsh), sisi kanan pipa berjalan dalam proses terpisah, sehingga variabel apa pun yang Anda atur dalam loop hilang. Misalnya, skrip penghitungan baris berikut mencetak 0 pada shell ini:
Solusinya adalah dengan meletakkan sisa skrip (atau setidaknya bagian yang membutuhkan nilai dari
$n
loop) dalam daftar perintah:Jika bertindak pada baris yang tidak kosong cukup baik dan inputnya tidak besar, Anda dapat menggunakan pemisahan kata:
Penjelasan: pengaturan
IFS
ke baris baru tunggal membuat pemisahan kata hanya terjadi di baris baru (sebagai lawan dari karakter spasi putih di bawah pengaturan default).set -f
mematikan globbing (yaitu ekspansi wildcard), yang jika tidak akan terjadi pada hasil substitusi perintah$(jobs)
atau substitusi variabel$foo
. Thefor
Loop bekerja pada semua bagian$(jobs)
, yang semua garis non-kosong di output perintah. Terakhir, kembalikan globbing danIFS
pengaturan.sumber
local IFS=something
. Itu tidak akan mempengaruhi nilai lingkup global. IIRC,unset IFS
tidak membuat Anda kembali ke default (dan tentu saja tidak berfungsi jika itu bukan default sebelumnya).Masalah: jika Anda menggunakan while, itu akan berjalan dalam subkulit dan semua variabel akan hilang. Solusi: gunakan untuk loop
sumber
while read
loop di bash berarti loop sementara dalam subkulit, sehingga variabel tidak global.while read;do ;done <<< "$var"
membuat loop body bukan subshell. (Bash baru-baru ini memiliki opsi untuk menempatkan tubuhcmd | while
loop tidak dalam subkulit, seperti yang selalu dimiliki ksh.)Dalam versi bash terbaru, gunakan
mapfile
ataureadarray
untuk secara efisien membaca output perintah ke dalam arrayPenafian: contoh yang mengerikan, tetapi Anda dapat dengan cepat menghasilkan perintah yang lebih baik untuk digunakan daripada diri Anda sendiri
sumber
readarray
fungsi dan memanggil fungsi beberapa kali.Referensi:
while
IFS
read
sumber
-r
juga merupakan ide bagus; Ini mencegah\` interpretation... (it is in your links, but its probably worth mentioning, just to round out your
IFS = `(yang sangat penting untuk mencegah kehilangan spasi putih)Anda dapat menggunakan <<< untuk membaca dari variabel yang berisi data yang dipisahkan dengan baris baru:
sumber