The &&
dan ||
operator tidak membalas penggantian inline untuk if-then-else. Meskipun jika digunakan dengan hati-hati, mereka dapat melakukan banyak hal yang sama.
Sebuah tes tunggal mudah dan jelas ...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
Namun, mencoba menambahkan beberapa tes dapat menghasilkan hasil yang tidak terduga ...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Mengapa FALSE dan TRUE digemakan?
Apa yang terjadi di sini adalah bahwa kita tidak menyadari itu &&
dan ||
adalah operator kelebihan beban yang bertindak berbeda di dalam kurung uji bersyarat [[ ]]
daripada yang mereka lakukan dalam daftar DAN dan ATAU (eksekusi bersyarat) yang kita miliki di sini.
Dari halaman bash (diedit) ...
Daftar
Daftar adalah urutan satu atau beberapa jaringan pipa yang dipisahkan oleh salah satu operator;, &, &&, atau ││, dan secara opsional diakhiri oleh salah satu dari,, &, atau. Dari daftar operator ini, && dan ││ memiliki prioritas yang sama, diikuti oleh; dan &, yang memiliki prioritas sama.
Urutan satu atau lebih baris baru mungkin muncul dalam daftar alih-alih tanda titik koma untuk membatasi perintah.
Jika perintah diakhiri oleh operator kontrol &, shell mengeksekusi perintah di latar belakang dalam sebuah subkulit. Shell tidak menunggu perintah selesai, dan status kembali adalah 0. Perintah dipisahkan oleh a; dieksekusi secara berurutan; shell menunggu setiap perintah berakhir pada gilirannya. Status kembali adalah status keluar dari perintah terakhir yang dijalankan.
Daftar AND dan OR adalah urutan dari salah satu dari lebih banyak pipa yang dipisahkan oleh operator kontrol&& dan ││. Daftar AND dan OR dijalankan dengan asosiasi kiri.
Daftar AND memiliki formulir ...
command1 && command2
Command2 dijalankan jika, dan hanya jika, command1 mengembalikan status keluar nol.
Daftar ATAU memiliki bentuk ...
command1 ││ command2
Command2 dijalankan jika dan hanya jika command1 mengembalikan status keluar yang tidak nol.
Status pengembalian daftar AND dan OR adalah status keluar dari perintah terakhir yang dijalankan dalam daftar.
Kembali ke contoh terakhir kami ...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Baik. Jika itu benar, lalu mengapa contoh berikutnya hingga terakhir menggemakan sesuatu?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
Risiko kesalahan logika saat menggunakan lebih dari satu &&
atau ||
dalam daftar perintah cukup tinggi.
Rekomendasi
Satu &&
atau ||
dalam daftar perintah berfungsi seperti yang diharapkan sehingga cukup aman. Jika ini adalah situasi di mana Anda tidak memerlukan klausa lain, sesuatu seperti yang berikut ini bisa lebih jelas untuk diikuti (kurung kurawal diperlukan untuk mengelompokkan 2 perintah terakhir) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Banyak &&
dan ||
operator, di mana setiap perintah kecuali yang terakhir adalah tes (yaitu di dalam tanda kurung [[ ]]
), biasanya juga aman karena semua tetapi operator terakhir berperilaku seperti yang diharapkan. Operator terakhir bertindak lebih seperti a then
atau else
klausa.
&&
dan||
shell seperticmd1 && cmd2 || cmd3
memiliki prioritas yang sama,&&
in((...))
dan[[...]]
memiliki prioritas lebih dari||
(((a || b && c))
is((a || (b && c)))
). Sama berlaku untuk-a
/-o
dalamtest
/[
danfind
dan&
/|
dalamexpr
.