Bash conditionals: how to “and” expressions? (jika [! -z $ VAR && -e $ VAR])


281

Saya kira saya tidak jelas tentang bagaimana melakukan tes "dan". Saya ingin memastikan ada argumen yang bekerja dengan baik [ -e $VAR ], tetapi ternyata itu juga mengevaluasi benar pada string kosong; yang tidak saya inginkan.

Bagaimana saya dan mereka bersama? Atau ada tes unary lain yang memenuhi apa yang saya inginkan?

Jawaban:


532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi

9
Solusi ini berfungsi bahkan dalam cangkang yang sepenuhnya sesuai dengan POSIX dan karenanya juga dalam bash; namun, untuk memanfaatkan sepenuhnya "bashism", lihat jawaban @ paxdiablo.
mklement0

2
Sangat senang melihat ini disarankan daripada yang usang -a.
Charles Duffy

1
Saya menemukan satu lagi penjelasan yang sangat bagus dan terperinci - stackoverflow.com/questions/3601515/…
valentt

70

Dari halaman bashmanual:

[[ expression ]] - mengembalikan status 0 atau 1 tergantung pada evaluasi ekspresi ekspresi bersyarat.

Dan, untuk ekspresi, salah satu opsi adalah:

expression1 && expression2- benar jika keduanya expression1dan expression2benar.

Jadi Anda bisa andbersama mereka sebagai berikut ( -nadalah kebalikan dari -zsehingga kita dapat menyingkirkan !):

if [[ -n "$var" && -e "$var" ]] ; then
    echo "'$var' is non-empty and the file exists"
fi

Namun, saya pikir itu tidak diperlukan dalam kasus ini, -e xyzzybenar jika xyzzy file tersebut ada dan dapat dengan mudah menangani string kosong. Jika itu yang Anda inginkan maka Anda sebenarnya tidak memerlukan -zcek kosong:

pax> VAR=xyzzy
pax> if [[ -e $VAR ]] ; then echo yes ; fi
pax> VAR=/tmp
pax> if [[ -e $VAR ]] ; then echo yes ; fi
yes

Dengan kata lain, cukup gunakan:

if [[ -e "$var" ]] ; then
    echo "'$var' exists"
fi

1
Kita dapat mempersingkatnya dengan[[ -e "$var" ]] && echo "'$var' exists"
jaypal singh

1
Ya, jika itu adalah satu-liner (seperti contoh saya). Saya tidak akan melakukan itu jika blok kondisional jauh lebih kompleks.
paxdiablo

dalam hal hanya ada satu - mungkin bahkan satu - perintah, masuk akal untuk menggunakan formulir ini karena lebih pendek
avp

9
if [ -n "$var" -a -e "$var" ]; then
    do something ...
fi

 


10
Karena POSIXtidak mendefinisikan perilaku [dengan set tes yang kompleks, kita harus menghindari menggunakan -aatau -odengan [. Saya membacanya di sini .
jaypal singh

2
@ jaypal-singh Anda benar, tetapi topik memiliki bashtag dan tidak menyebutkan tentang POSIX, jadi saya memposting versi ini yang berfungsi di bawah bashdan beberapa shell modern lainnya.
Slava Semushin

2
Jika Anda mengasumsikan penggunaan bashatau kerang modern lainnya, bahkan ada lebih sedikit alasan untuk merekomendasikan -a.
chepner

Bahkan dengan bash, cara tes ini berperilaku tidak didefinisikan dengan baik dalam semua kasus sudut. Pertimbangkan [ "$var1" -o "$var2" ]; jika var1=(dan var2=), maka yang kita miliki adalah ujian apakah -otidak kosong, bukan apakah salah satu var1atau var2tidak kosong. Ambiguitas semacam ini adalah satu-satunya alasan yang sah untuk x$varungkapan dalam testperintah modern (yaitu, pasca-90-an) dengan kutipan yang benar, dan idiom itu harus mati dalam api.
Charles Duffy

4

Cukup kutip variabel Anda:

[ -e "$VAR" ]

Ini mengevaluasi [ -e "" ]apakah $VARkosong.

Versi Anda tidak berfungsi karena dievaluasi ke [ -e ]. Sekarang dalam kasus ini, bash hanya memeriksa apakah argumen tunggal ( -e) adalah string yang tidak kosong.

Dari halaman manual:

menguji dan [mengevaluasi ekspresi kondisional menggunakan seperangkat aturan berdasarkan jumlah argumen. ...

1 argumen

Ungkapannya benar jika dan hanya jika argumennya tidak nol.

(Juga, solusi ini memiliki manfaat tambahan untuk bekerja dengan nama file yang mengandung spasi)


1

Saya menemukan jawaban sekarang. Terima kasih atas saran Anda!

for e in ./*.cutoff.txt; do
if grep -q -E 'COX1|Cu-oxidase' $e
then
    echo xyz >$e.match.txt
else
    echo
fi

if grep -q -E 'AMO' $e
then
    echo abc >$e.match.txt
else
    echo
fi; done

Ada komentar tentang itu? Tampaknya tidak efisien untuk melakukan grep dua kali, tetapi berhasil ...

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.