Bash conditionals: วิธีการ“ และ” การแสดงออก? (ถ้า [! -z $ VAR && -e $ VAR])


281

ฉันเดาว่าฉันยังไม่ชัดเจนเกี่ยวกับวิธีการทดสอบ "และ" ฉันต้องการตรวจสอบให้แน่ใจว่ามีการโต้แย้งที่ใช้งานได้ดี[ -e $VAR ]แต่กลับกลายเป็นว่าการประเมินนั้นเป็นจริงในสตริงว่าง ซึ่งฉันไม่ต้องการ

ฉันจะ 'และ' พวกเขาเข้าด้วยกันได้อย่างไร หรือมีการทดสอบ unary อื่นที่ทำสิ่งที่ฉันต้องการได้หรือไม่

คำตอบ:


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

9
การแก้ปัญหานี้ทำงานได้แม้อยู่ในเปลือกหอยอย่างเคร่งครัด POSIX สอดคล้องและดังนั้นจึงยังอยู่ในbash; อย่างไรก็ตามเพื่อใช้ประโยชน์จาก "bashisms" อย่างเต็มที่โปรดดูคำตอบของ @ paxdiablo
mklement0

2
-aดีใจมากที่เห็นนี้ได้รับคำแนะนำแทนคร่ำครึ
Charles Duffy

1
ฉันพบคำอธิบายที่ยอดเยี่ยมและละเอียดอย่างหนึ่ง - stackoverflow.com/questions/3601515/…
valentt

70

จากbashmanpage:

[[ expression ]] - คืนสถานะ 0 หรือ 1 ขึ้นอยู่กับการประเมินผลของนิพจน์เงื่อนไขนิพจน์

และสำหรับนิพจน์หนึ่งในตัวเลือกคือ:

expression1 && expression2- เป็นจริงถ้าทั้งสองexpression1และexpression2เป็นจริง

ดังนั้นคุณสามารถandรวมเข้าด้วยกันดังต่อไปนี้ ( -nตรงข้าม-zเพื่อให้เราสามารถกำจัด!):

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

อย่างไรก็ตามฉันไม่คิดว่ามันจำเป็นในกรณีนี้-e xyzzyเป็นจริงหากxyzzy ไฟล์นั้นมีอยู่และสามารถจัดการกับสตริงว่างได้อย่างง่ายดาย ถ้านั่นคือสิ่งที่คุณต้องการจากนั้นคุณไม่จำเป็นต้องมี-zเช็คเปล่า:

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

ในคำอื่น ๆ เพียงใช้:

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

1
เราสามารถย่อให้สั้นลงด้วย[[ -e "$var" ]] && echo "'$var' exists"
jaypal singh

1
ใช่ถ้าเป็นหนึ่งซับ (ตามตัวอย่างของฉัน) ฉันจะไม่ทำอย่างนั้นถ้าบล็อกเงื่อนไขมีความซับซ้อนมากกว่านี้
paxdiablo

ในกรณีที่มีเพียงหนึ่ง - บางทีแม้แต่อย่างใดอย่างหนึ่ง - คำสั่งก็จะทำให้ความรู้สึกที่จะใช้รูปแบบนี้มันจะสั้น
AVP

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

 


10
เนื่องจากPOSIXไม่ได้กำหนดลักษณะการทำงานของ[ชุดที่ซับซ้อนของการทดสอบเราควรหลีกเลี่ยงการใช้-aหรือมี-o [ฉันอ่านมันนี่
jaypal singh

2
@ jaypal-singh คุณพูดถูก แต่หัวข้อมีbashแท็กและไม่พูดถึง POSIX ดังนั้นฉันจึงโพสต์เวอร์ชั่นนี้ซึ่งใช้งานได้ภายใต้bashและเชลล์สมัยใหม่อื่น ๆ
Slava Semushin

2
หากคุณกำลังสมมติว่าใช้bashหรือเปลือกที่ทันสมัยอื่น ๆ มีแม้แต่น้อย-aเหตุผลที่จะแนะนำ
chepner

ถึงแม้จะมี bash แต่วิธีการทดสอบเหล่านี้ยังไม่ชัดเจนในทุกกรณี พิจารณา[ "$var1" -o "$var2" ]; ถ้าvar1=(และvar2=)แล้วสิ่งที่เรามีคือการทดสอบสำหรับว่า-oไม่ว่างมากกว่าไม่ว่าจะเป็นอย่างใดอย่างหนึ่งvar1หรือvar2ไม่เป็นที่ว่างเปล่า ความคลุมเครือแบบนี้เป็นเพียงเหตุผลที่ถูกต้องสำหรับx$varสำนวนในtestคำสั่งสมัยใหม่ (นั่นคือโพสต์ - 90s) ด้วยคำพูดที่ถูกต้องและสำนวนนั้นต้องตายในกองไฟ
Charles Duffy

4

เพียงแค่พูดตัวแปรของคุณ:

[ -e "$VAR" ]

สิ่งนี้จะประเมิน[ -e "" ]ว่า$VARว่างหรือไม่

รุ่นของคุณใช้งานไม่ได้เพราะประเมินผล[ -e ]แล้ว ตอนนี้ในกรณีนี้ทุบตีเพียงตรวจสอบว่าอาร์กิวเมนต์เดียว ( -e) เป็นสตริงที่ไม่ว่างเปล่า

จาก manpage:

ทดสอบและ [ประเมินนิพจน์แบบมีเงื่อนไขโดยใช้ชุดของกฎตามจำนวนอาร์กิวเมนต์ ...

1 อาร์กิวเมนต์

การแสดงออกเป็นจริงหากว่าข้อโต้แย้งนั้นไม่เป็นโมฆะ

(นอกจากนี้โซลูชันนี้ยังมีประโยชน์เพิ่มเติมในการทำงานกับชื่อไฟล์ที่มีช่องว่าง)


1

ฉันพบคำตอบแล้ว ขอบคุณสำหรับคำแนะนำของคุณ!

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

ความคิดเห็นใด ๆ ดูเหมือนว่าการ grep ไม่มีประสิทธิภาพสองครั้ง แต่ใช้งานได้ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.