Iterate atas output dari perintah di bash tanpa subshell

9

Saya ingin mengulang output dari perintah tanpa membuat sub-shell atau menggunakan file sementara.

Versi awal skrip saya terlihat seperti ini, tetapi ini tidak berfungsi karena ia membuat subkulit, dan exitperintah mengakhiri subkulit bukan skrip utama yang diperlukan. Ini adalah bagian dari skrip yang lebih besar untuk mengonfigurasi perutean kebijakan, dan menghentikan eksekusi jika mendeteksi suatu kondisi yang akan menyebabkan perutean gagal.

sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do

  if [[ "0" != "${RPSTAT[2]}" ]] ; then
    echo >&2 "RP Filter must be disabled on all interfaces!"
    echo >&2 "The RP filter feature is incompatible with policy routing"
    exit 1
  fi
done

Jadi salah satu alternatif yang disarankan adalah menggunakan perintah seperti ini untuk menghindari subkulit.

while read BLAH ; do echo $BLAH; done </root/regularfile

Jadi menurut saya saya juga harus dapat menggunakan perintah seperti ini untuk menghindari subshell dan masih mendapatkan output dari program yang saya inginkan.

while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Sayangnya, menggunakan perintah itu menghasilkan kesalahan ini.

-bash: syntax error near unexpected token `<(sysct ...

Saya benar-benar bingung karena ini berhasil.

cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Saya bisa menyimpan output dari perintah itu ke file sementara, dan menggunakan redirect pada file sementara, tetapi saya ingin menghindari melakukan itu.

Jadi mengapa pengalihan memberi saya kesalahan, dan apakah saya memiliki opsi selain membuat file sementara?

Sakit kepala
sumber

Jawaban:

13

Anda melewatkan <. Seharusnya:

while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Pikirkan <(sysctl -a 2>/dev/null | grep '\.rp_filter')sebagai file.

dogbane
sumber
Terima kasih banyak. Hanya untuk perbaikan saya, dapatkah saya mengarahkan halaman manual, bantuan, atau halaman web, yang mendokumentasikan ini? Saya tidak bisa membuat Google menunjukkan saya pada sesuatu yang berguna saat mencoba mencari ini.
Zoredache
2
Google "memproses substitusi". mis. tldp.org/LDP/abs/html/abs-guide.html#PROCESS-SUB
dogbane
Perlu dicatat bahwa substitusi <() menggunakan deskriptor file dan pada beberapa sistem operasi akan membuat & menggunakan file sementara secara transparan.
ewindisch
@Zoredache: Cukup cari <(di manual bash (ini berada di bawah "substitusi proses").
Gilles 'SO- stop being evil'
@ewindisch, jika alat secara transparan membuat tempfile yang baik-baik saja, saya hanya tidak ingin membuatnya secara manual, ketika saya cukup yakin saya tidak perlu melakukannya.
Zoredache
0

Untuk beberapa alternatif lagi jika ada yang datang ke sini lagi ...

Bergantung pada shell, Anda mungkin bisa menggunakan set -o errexitagar shell induk keluar ketika perintah (termasuk subkulit) keluar tidak nol tanpa terjebak dalam ifblok atau trailing &&atau ||, seperti dalam

/bin/false || echo "ignoring error"

Atau, Anda dapat meminta sinyal subshell yang digunakan orang tua untuk membunuh dan variabel lingkungan $ PPID, jika tersedia.

Atau Anda bisa memindahkan blok sementara ke fungsi dan mengembalikan 0/1 (secara eksplisit mengembalikan 0 setelah blok sementara) dan lakukan saja seperti pipa Anda sysctl | grep | function || exit. Saya kira Anda bisa meletakkan pengembalian di blok inline juga, tetapi fungsi adalah teman Anda. ;)

dannysauer
sumber