Saya punya perintah mengembalikan beberapa baris. Untuk pemrosesan lebih lanjut, saya perlu memproses setiap baris dari baris tersebut.
Kode saya saat ini berfungsi dengan memodifikasi IFS ( Pemisah Bidang Internal ):
ROWS=$(some command returning multiple lines)
O=$IFS #save original IFS
IFS=$(echo -en "\n\b") # set IFS to linebreak
for ROW in ${ROWS[@]}
do
echo "$ROW"
done
IFS=$O #restore old IFS
Saya bertanya-tanya, apakah ada cara yang lebih baik untuk mengakses satu baris dari beberapa garis keluaran, satu tanpa memodifikasi IFS? Terutama keterbacaan skrip saya menjadi buruk dengan memodifikasi IFS.
Pembaruan: Saya mengalami masalah untuk mendapatkan jawaban berfungsi, mis. Yang dari choroba:
while IFS= read -r line ; do
let var+=line #line 42
done << $(sqlite3 -list -nullvalue NULL -separator ',' /var/log/asterisk/master.db "${QUERY}")
echo "$var" # line 44
memberi saya
./bla.sh: row 44: Warning: here-document at line 43 delimited by end-of-file (wanted `$(sqlite3 -list -nullvalue NULL -separator , /var/log/asterisk/master.db ${QUERY})')
./bla.sh: row 42: let: echo "": syntax error: invalid arithmetic operator. (error causing character is \"""\").
Adakah yang bisa membantu saya dengan ini? Terima kasih!
bash
shell
command
command-substitution
stefan.at.wpf
sumber
sumber
< <(some command returning multiple lines)
, tetapi bukan itu yang Anda lakukan.Jawaban:
Bagaimana dengan
read
dalam satuwhile
lingkaran?Hati-hati, meskipun, pipa dijalankan dalam subkulit, yang berarti Anda tidak dapat mengubah nilai variabel untuk sisa skrip. Jika Anda membutuhkan sesuatu untuk bertahan dari loop sementara Anda, Anda dapat menggunakan subtitusi proses bash:
sumber
bash
, tetapi perlu dicatat bahwa cakupan subkulit variabel hanya masalahbash
, melakukan hal yang samazsh
tidak akan memiliki masalah ini sama sekali.Pengaturan
IFS
ke baris baru saja tidak cukup. (Ngomong-ngomong, kamu juga membelah karakter backspace?)Dalam kode Anda,
${ROWS[@]}
(yang merupakan cara aneh untuk menulis$ROWS
-ROWS
bukan array) tidak dikutip ganda. (Jika berada di dalam tanda kutip ganda, Anda akan mendapatkan string tunggal, karenaROWS
bukan array.) Jadi shell membagi nilai variabel menjadi bidang pada setiapIFS
karakter, lalu memperlakukan setiap bidang sebagai pola gumpalan. Misalnya, jika salah satu baris yang dicetak oleh perintah berisi karakter tunggal*
, ini akan diganti dengan nama file di direktori saat ini.Anda dapat mematikan globbing dengan
set -f
. Dalam kebanyakan kasus di mana Anda mengaturIFS
untuk menggunakan fitur pemecahan bidang shell, Anda juga perlu mematikan globbing. Nyalakan kembaliset +f
.Ungkapan yang dapat diandalkan untuk membaca baris output perintah demi baris adalah
while IFS= read -r
.Perhatikan bahwa sebagian besar shell menjalankan setiap perintah pipa dalam subkulit yang terpisah. Jadi jika Anda perlu mengatur variabel dan menggunakannya setelah loop, bungkus perintah ini dalam grup bersama dengan loop. (Ksh dan zsh adalah pengecualian, mereka menjalankan perintah terakhir dari pipeline di shell induk.)
sumber
Anda sedang mencampur sintaks di sini-dokumen dan di sini-string dalam pertanyaan pembaruan Anda.
Baik gunakan di sini-dokumen:
Atau di sini-string:
sumber