Apakah ada cara untuk membaca baris dari output perintah?

8

Saya punya perintah proses awal untuk menampilkan file

./preprocess.sh > preprocessed_file 

dan preprocessed_fileakan digunakan seperti ini

while read line
do

    ./research.sh $line &

done < preprocessed_file 

rm -f preprocessed_file

Apakah ada cara untuk mengarahkan output ke while read linebagian daripada keluaran ke preprocessed_file? Saya pikir harus ada cara yang lebih baik selain menggunakan temp ini preprocessed_file.

Marcus Thornton
sumber

Jawaban:

8

Anda dapat menggunakan subtitusi proses bash :

while IFS= read -r line; do
  ./research.sh "$line" &
done < <(./preprocess.sh)

Beberapa keuntungan dari substitusi proses:

  • Tidak perlu menyimpan file sementara.
  • Performa yang lebih baik. Membaca dari proses lain sering kali lebih cepat daripada menulis ke disk, lalu membaca kembali.
  • Hemat waktu untuk perhitungan karena ketika dilakukan bersamaan dengan ekspansi parameter dan variabel, penggantian perintah, dan ekspansi aritmatika
cuonglm
sumber
apa arti dari panah kiri ganda (<<)?
Marcus Thornton
@MarcusThornton: <adalah pengalihan, sedangkan <(...)sintaksis subtitusi proses. Anda harus membaca: gnu.org/software/bash/manual/html_node/… untuk lebih jelasnya.
cuonglm
Oke. <(...)adalah bagian dari sintaksis.
Marcus Thornton
2
Ini belum tentu lebih cepat. Karena ketika membaca dari sebuah pipa readharus membaca satu byte pada satu waktu, sementara itu dapat mengoptimalkan hal-hal dengan membaca potongan yang lebih besar dan mencari ke belakang ketika membaca dari file biasa. Yang terbaik adalah menghindari while readloop sama sekali di tempat pertama bila memungkinkan. Perhatikan juga bahwa Anda perlu IFS= read -r linemembaca baris $line. Dan meninggalkan tanda $linekutip (memanggil operator + glob glob) di sini mungkin tidak masuk akal.
Stéphane Chazelas
1
@mikeserv, perintah sering line-buffer (berlawanan dengan full-buffer) outputnya ketika masuk ke terminal. Di sini saya mengatakan bahwa readshell builtin membaca satu karakter pada saat membaca dari pipa (terlepas dari apa yang ada di ujung pipa yang readtidak memiliki cara untuk mengetahui), yang merupakan salah satu alasan mengapa while readloop sangat lambat.
Stéphane Chazelas
15

Iya! Anda dapat menggunakan pipa proses |.

./preprocess.sh |
    while IFS= read -r line
    do
        ./research.sh "$line" &
    done

Pipa proses melewatkan output standar ( stdout) dari satu proses ke input standar ( stdin) dari proses berikutnya.

Anda bisa menempatkan karakter baris baru mengikuti a |dan memperluas perintah ke baris berikutnya.

Catatan: a|bsetara dengan b < <(a), tetapi tanpa file ajaib, dan dalam urutan yang lebih mudah dibaca, terutama ketika pipa menjadi lebih panjang.

a|b|c setara dengan c < <(b < <(a))

dan

a|b|c|d|e adalah e < < (d < <(c < <(b < <(a))))

ctrl-alt-delor
sumber
3
Catatan: Solusi dengan pipa ini memiliki keuntungan menjadi lebih portabel daripada substitusi proses (tidak didukung oleh beberapa cangkang POSIX seperti dasbor). Masih menyangkut portabilitas, sisi kanan pipa dapat dieksekusi dalam subkulit (ini tergantung pada shell), sehingga efek samping apa pun (seperti variabel pengaturan) tidak dapat memengaruhi lingkungan skrip shell.
vinc17
Biasanya lebih aman untuk memasukkan referensi variabel seperti $lineke dalam tanda kutip ganda (misalnya, dalam skrip Anda, ./research.sh "$line" &).
G-Man Mengatakan 'Reinstate Monica'
1
@ G-Man Mungkin tidak dalam konteks ini. Jika research.shbekerja dengan array argumen baris perintah dan $line, misalnya, "satu dua", dengan maksud bahwa argumen pertama menjadi "satu" dan argumen kedua "dua", mengutip $lineakan membuat hal itu tidak mungkin - sebaliknya argumen pertama akan menjadi "satu dua" dan tidak akan ada yang kedua ...
goldilocks
2
" a|bsetara denganb < <(a) " - tutup, tetapi tidak cukup. Dalam versi pipa, kedua sisi pipa dijalankan dalam subkulit, sedangkan dalam versi proses-substitusi, hanya proses tersubstitusi yang dijalankan dalam subkulit, tetapi adijalankan dalam lingkup level shell yang saat ini sedang dijalankan. Ini memiliki implikasi penting untuk ruang lingkup variabel yang ditetapkan dalama
Digital Trauma