ไวยากรณ์ของเงื่อนไขที่ซับซ้อนในเชลล์คืออะไร


11

หากต้องการแสดงการทดสอบต่อไปนี้ใน shell (sh):

if ( a == 1 && ( b == 1 || b == 2 )) { ... }

จนถึงตอนนี้สิ่งที่ดีที่สุดที่ฉันสามารถเขียนได้คือ:

if [[ $a -eq 1 ]]; then
  if [[ $b -eq 1 || $b -eq 2 ]]; then
     ...
  fi
fi

ฉันไม่ทราบวิธีการรวม && และ || ด้วยลำดับความสำคัญที่ถูกต้อง Googling ไม่ได้ให้คำตอบใด ๆ แก่ฉัน (แบบฝึกหัดให้ตัวอย่างพื้นฐานเท่านั้นถ้ามี)

ไวยากรณ์ที่จะรวมทั้งสองคืออะไรถ้าเป็นหนึ่ง?


1
เหตุผลใดที่จะไม่ใช้ksh? จากนั้นรหัสเริ่มต้นของคุณจะต้องใช้วงเล็บอีกหนึ่งคู่เท่านั้น:if (( a == 1 && ( b == 1 || b == 2 ))); then :; fi
จัดการ

คำตอบ:


15

โปรดทราบว่าไม่ได้[[ ]]อยู่ใน Bourne หรือ POSIXshPOSIX สำหรับshไวยากรณ์ที่แท้จริงมีหลายวิธีในการทำเช่นนี้

ใช้เพียง[ ]คู่เดียวเท่านั้น

if [ 1 -eq "$a" -a \( 1 -eq "$b" -o 2 -eq "$b" \) ]; then
    # ...
fi

หรือหลีกเลี่ยง POSIX -aและ-oตัวเลือก1

if [ 1 -eq "$a" ] && { [ 1 -eq "$b" ] || [ 2 -eq "$b" ]; }; then
    # ...
fi

1เหตุผลหนึ่งสำหรับการหลีกเลี่ยง-aและ-oพกพาสูงสุด - ไม่ได้ทั้งหมดtestหรือ[การใช้งานที่สามารถจัดการมากกว่า 4 ข้อโต้แย้งซึ่งเป็นสิ่งที่คุณได้รับถ้าคุณห่วงโซ่การแสดงออกด้วย-aและและ-o\( \)


สคริปต์ของฉันมี#! bin / sh / shebang และเปลือกเริ่มต้นคือksh ทำไมจะไม่ใช้ sh
Offirmo

2
@Offirmo ถ้าคุณประกาศสคริปต์ของคุณเป็นมันเป็นเรื่องที่ไม่ถูกต้องในการเขียนสคริปต์ที่ใช้คุณลักษณะไม่ได้อยู่ใน/bin/sh shคุณควรจะตระหนักว่าkshไม่ใช่แต่เป็นซูเปอร์sh shหากคุณนำสคริปต์ksh-but-declar-as- shไปยังระบบที่shไม่ใช่ symlink kshระบบอาจหยุดทำงาน คุณสามารถหลีกเลี่ยงปัญหานั้นได้โดยทำให้แน่ใจว่าสคริปต์ของคุณตรงกับคำประกาศ
jw013

ผมคิดว่าการตั้งค่า/ bin / ดวลจุดโทษเป็น shebang จะทำให้สคริปต์ของฉันเรียกผ่านbin / คุณหมายถึงว่าเปลือกเริ่มต้นของฉัน (ksh) ไม่สนใจ Shebang และตีความมันโดยตรงหรือไม่
Offirmo

@Offirmo คุณถูกต้อง: ก shebang ของจะเรียก/bin/sh /bin/shปัญหาคือไม่ยอมรับ/bin/sh [[คุณไม่สามารถใช้[[หรือใช้เปลือกที่ยอมรับ[[เช่นkshใน shebang ของคุณ
jw013

2
ปัญหาไม่ได้มีมากที่-a/ -oไม่ได้รับการสนับสนุนจากการใช้งานบางอย่าง แต่มันไม่น่าเชื่อถือสำหรับข้อโต้แย้งโดยพลการ Like [ "$a" = "$b" -o "$b" = "$c" ]จะล้มเหลวสำหรับค่าของ$alike ที่!มี[การนำไปใช้งานหลายอย่าง
Stéphane Chazelas

2

ฉันลองใช้ไวยากรณ์และพบว่า

if [[ $a -eq 1 ]] && [[ $b -eq 1 || $b -eq 2 ]]; then
 ...
fi

กำลังทำงาน


1
ใช้ได้กับเวอร์ชั่นทุบตีด้านบน 4
Nikhil Mulley


0

วิธีที่ถูกต้องในการทำด้วยเพียงshell:

if test 1 -eq "$a" && test 1 -eq "$b" -o 2 -eq "$b"; then 
    ...
fi

คำอธิบาย:

testที่นี่ทำหน้าที่เป็นวงเล็บและ-oเป็นตรรกะหรือ หากคุณตรรกะและภายใน "วงเล็บ" -aคุณจะใช้

เพิ่มเติมเกี่ยวกับที่สามารถพบได้ที่นี่

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