Saya ingin mewakili beberapa kondisi seperti ini:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
tetapi ketika saya menjalankan skrip, itu menunjukkan
syntax error at line 15: `[' unexpected,
di mana baris 15 adalah yang menunjukkan jika ....
Apa yang salah dengan kondisi ini? Saya kira ada yang salah dengan ()
.
test
([
) dan bukan oleh shell. Shell hanya mengevaluasi status keluar dari[
.Jawaban:
Teknik klasik (escape metacharacters):
Saya telah menyertakan referensi
$g
dalam tanda kutip ganda; itu praktik yang baik, secara umum. Secara ketat, tanda kurung tidak diperlukan karena diutamakan-a
dan-o
membuatnya benar bahkan tanpa mereka.Perhatikan bahwa operator
-a
dan-o
merupakan bagian dari spesifikasi POSIX untuktest
alias[
, terutama untuk kompatibilitas mundur (karena mereka adalah bagian daritest
UNIX Edisi ke-7, misalnya), tetapi mereka secara eksplisit ditandai sebagai 'usang' oleh POSIX. Bash (lihat ekspresi kondisional ) tampaknya mendahului makna klasik dan POSIX untuk-a
dan-o
dengan operator alternatifnya sendiri yang mengambil argumen.Dengan hati-hati, Anda dapat menggunakan
[[
operator yang lebih modern , tetapi perlu diketahui bahwa versi di Bash dan Korn Shell (misalnya) tidak harus sama.Contoh jalankan, menggunakan Bash 3.2.57 pada Mac OS X:
Anda tidak perlu mengutip variabel
[[
seperti yang Anda lakukan[
karena itu bukan perintah yang terpisah dengan cara yang[
sama.Saya akan berpikir begitu. Namun, ada alternatif lain, yaitu:
Memang, jika Anda membaca pedoman 'shell portabel' untuk
autoconf
alat atau paket terkait, notasi ini - menggunakan '||
' dan '&&
' - adalah apa yang mereka rekomendasikan. Saya kira Anda bahkan bisa pergi sejauh:Jika tindakannya sepele seperti gema, ini tidak buruk. Ketika blok aksi yang akan diulang adalah beberapa baris, pengulangan terlalu menyakitkan dan salah satu versi sebelumnya lebih disukai - atau Anda perlu membungkus aksi menjadi fungsi yang dipanggil dalam
then
blok yang berbeda .sumber
-a
sebenarnya memiliki prioritas lebih tinggi daripada-o
(tidak seperti&&
dan||
di shell - namun, di dalambash
[[ ... ]]
kondisional ,&&
juga memiliki prioritas lebih tinggi daripada||
). Jika Anda ingin menghindari-a
dan-o
untuk kekokohan dan portabilitas maksimum - yang halaman manual POSIX sendiri sarankan - Anda juga dapat menggunakan subkulit untuk pengelompokan:if ([ $g -eq 1 ] && [ "$c" = "123" ]) || ([ $g -eq 2 ] && [ "$c" = "456" ])
if test "$g" -eq 1 -a "$c" = "123" || test "$g" -eq 2 -a "$c" = "456"; then ...
&&
atau||
juga lebih disukai karena berperilaku lebih seperti conditional dalam bahasa lain, dan memungkinkan Anda kondisi arus pendek. Sebagai contoh:if [ -n "${check_inodes}" ] && [ "$(stat -f %i "/foo/bar")" = "$(stat -f %i "/foo/baz")" ]
. Melakukannya dengan cara ini, jikacheck_inodes
kosong, Anda menghindari dua panggilanstat
, sedangkan kondisi pengujian yang lebih besar dan kompleks harus memproses semua argumen sebelum mengeksekusi (yang juga dapat menyebabkan bug jika Anda lupa tentang perilaku itu).Di Bash:
sumber
bash
. Sebagai tambahan: dalam kasus khusus ini tanda kurung bahkan tidak diperlukan, karena kondisional di dalam sebenarnya memiliki prioritas lebih tinggi daripada - tidak seperti di luar kondisional seperti itu.[[ ... ]]
&&
||
if
/else
pernyataan dan memiliki kode antarathen
danfi
memasukkan fungsi untuk menghindari mengulanginya. Dalam kasus yang sangat sederhana, Anda bisa menggunakancase
pernyataan dengan;&
fallthrough (dalam Bash 4).Menggunakan
/bin/bash
yang berikut ini akan berhasil:sumber
Hati-hati jika Anda memiliki spasi di variabel string Anda dan Anda memeriksa keberadaannya. Pastikan untuk mengutipnya dengan benar.
sumber
sumber
{ ;}
bisa digunakan sebagai gantinya.Dalam bash untuk perbandingan string, Anda dapat menggunakan teknik berikut.
Contoh:
sumber
sumber
Anda juga dapat membuat lebih dari 2 kondisi:
sumber