Pipa B ke D? - A && B || C | D


14

Apakah ada cara untuk menulis ulang struktur perintah A && B || C | Dsehingga B atau C disalurkan ke D?

Dengan perintah saat ini, hanya B atau C dan D yang dijalankan.

Sebagai contoh:

masukkan deskripsi gambar di sini

Jawaban:


31

Ya, di bash Anda dapat menggunakan tanda kurung:

(A && B || C) | D

Dengan cara ini, output dari A && B || Cakan disalurkan ke D.


6
Atau A && (B || C) | D, jika Anda tidak ingin B, C, atau D berjalan ketika A gagal
zwol

2
Anda juga dapat menggunakan parens di sh:)
EKons

Tidak jelas apakah menggunakan kurung bukannya kurung kurawal adalah keputusan yang disengaja (jika demikian, apa manfaatnya?) Atau hanya pengawasan. Bisakah Anda jelaskan?
Tom Fenech

@TomFenech Parens menyebabkan ekspresi berjalan di sub-shell, yang merupakan proses (tunggal) terpisah dari POV dari sisa skrip. Oleh karena itu, apa pun output dari ekspresi di dalam parens, itu akan disalurkan bersama. (Karena Aada di dalam subkulit, ini juga termasuk A.)
jpaugh

1
@ jpaugh Saya pikir poin Anda tentang isolasi adalah bagus, tetapi hasilnya akan disalurkan dengan cara yang sama ketika menggunakan kurung kurawal, bukan?
Tom Fenech

14

Anda dapat menulis ini sebagai

if A; then B; else C; fi | D

Anda mengatakan ingin menjalankan salah satu Batau C, tetapi A && B || Ctidak mencapai itu. Jika Aberhasil, tetapi Bberjalan dan gagal, itu akan dijalankan C.

Catatan 1: jika Anda entah bagaimana dapat menjamin bahwa Bselalu berhasil dan ingin tetap dengan versi pendek, maka saya masih akan memilih

{ A && B || C; } | D

lebih ( ... ), karena yang terakhir tidak perlu memaksa subkulit baru untuk dibuat, yang mungkin atau mungkin tidak dioptimalkan.

Catatan 2: kedua bentuk menganggap Atidak menghasilkan output, yang benar dalam contoh Anda tetapi tidak harus demikian pada umumnya. Itu bisa dihindari dengan

A; if [ "$?" -eq 0 ]; then B; else C; fi | D

Apakah Anda yakin itu { … }tidak memaksa subshell dibuat karena pipa? Saya mengamati perilaku berikut: pgrep bashdan pgrep bash | catdan if true; then pgrep bash; fidan { pgrep bash; }memiliki satu garis keluaran; ( pgrep bash; )dan ( pgrep bash; ) | catdan { pgrep bash; } | catdan if true; then pgrep bash; fi | catmemiliki dua jalur output.
wchargin

@wchargin ... | ...menyebabkan subkulit dibuat, itu tidak dapat dihindari. ( ... ), setidaknya dalam teori, menyebabkan subkulit tambahan dibuat yang { ...; }menghindari, tapi itulah yang saya maksud dengan "mungkin atau mungkin tidak dioptimalkan": ada kemungkinan bahwa dalam kasus khusus ini, shell menyadari itu tidak masalah, efeknya akan sama.
hvd

5

Jawaban accepter benar tetapi tidak mencakup kasus penggunaan potensial untuk tidak memiliki output Asebagai input D. Untuk mencapai itu, Anda memerlukan pengalihan aliran Atergantung pada kebutuhan Anda.

  • Jika Anda ingin membuang output A:

    { A >/dev/null && B || C; } | D
  • Jika Anda ingin melihat output Apada terminal:

    { A >/dev/tty && B || C; } | D
  • Jika Anda membutuhkan output Asebagai input dari perintah selanjutnya EAnda akan memerlukan grup perintah tambahan dan pengalihan aliran:

    { { A >&3 && B || C; } | D; } 3>&1 | E

Jika semua ini terlihat terlalu misterius bagi Anda (seperti halnya bagi saya), saya sarankan Anda menggunakan variabel shell khusus untuk status keluar Adan bekerja dengan itu:

A
if [ $? -eq 0 ]; then
  B
else
  C
fi |
D

Jika Anda ingin lebih ringkas tetapi tidak terlalu misterius saya sarankan ini:

A; { [ $? -eq 0 ] && B || C; } | D

(Lihat juga bagian terakhir dari jawaban hvd yang tidak saya perhatikan ketika saya menulis jawaban asli saya.)


Jawaban saya mencakup hal itu. Lihat apa yang saya masukkan ke "Catatan 2:", di mana saya cukup pindah Adari saluran pipa.
hvd

@ DVD: Anda benar dan terima kasih telah menunjukkan bagian dari jawaban Anda kepada saya! Saya mengubah klaim saya dan memberi Anda kredit yang sesuai.
David Foerster
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.