ทุบตีถ้าคำสั่งที่มีหลายเงื่อนไขพ่นข้อผิดพลาด


165

ฉันพยายามเขียนสคริปต์ที่จะตรวจสอบสถานะข้อผิดพลาดสองรายการและในกรณีที่มีการเปลี่ยนแปลงสถานะหนึ่ง (หรือทั้งสองอย่าง) มันจะเกิดข้อผิดพลาดขึ้น สคริปต์ของฉัน:

my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" &&     "$my_error_flag_o"="2" ]]; then
    echo "$my_error_flag"
else
    echo "no flag"
fi

โดยพื้นฐานแล้วควรมีบางสิ่งพร้อม:

if ((a=1 or b=2) or (a=1 and b=2))
  then
     display error
else
     no error
fi

ข้อผิดพลาดที่ฉันได้รับคือ:

 line 26: conditional binary operator expected
 line 26: syntax error near `]'
 line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'

ขายึดของฉันยุ่งหรือไม่



2
ใช้วงเล็บ - ()
AlikElzin-kilaka


3
มีเหตุผลa==1 or b==2ครอบคลุมกรณีที่a==1 and b==2แล้ว การทดสอบแยกต่างหากสำหรับสิ่งที่เกินความจำเป็นอย่างสมบูรณ์ที่นี่
tripleee

คำตอบ:


249

ใช้การดำเนินการ-a(สำหรับและ) และ-o(สำหรับหรือ)

tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

ปรับปรุง

จริงๆแล้วคุณยังสามารถใช้&&และ||กับการ-eqดำเนินการ ดังนั้นสคริปต์ของคุณจะเป็นเช่นนี้:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
      echo "$my_error_flag"
else
    echo "no flag"
fi

แม้ว่าในกรณีของคุณคุณสามารถละทิ้งสองนิพจน์สุดท้ายและเพียงแค่ใช้อย่างใดอย่างหนึ่งหรือการดำเนินการเช่นนี้:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ]; then
      echo "$my_error_flag"
else
    echo "no flag"
fi

3
@Simply_Me: ไม่ตรรกะหรือเป็นจริงหากตัวถูกดำเนินการทั้งสองหรือทั้งคู่เป็นจริง คุณกำลังคิดถึง "เอกสิทธิ์หรือ" (XOR) ซึ่งเป็นจริงถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นจริง (ที่จริงแล้วมีรุ่นของ XOR ที่ทำงานกับตัวถูกดำเนินการมากกว่า 2 ตัวซึ่งในกรณีนี้จะเป็นจริงถ้าตัวถูกดำเนินการจำนวนคี่เป็นจริง)
Gordon Davisson

4
BTW ปัญหาในรหัสต้นฉบับนั้นรวมถึงการใช้[และ]การจัดกลุ่ม (พวกเขาไม่ทำเช่นนั้น) และไม่สามารถใส่ช่องว่างรอบตัวดำเนินการ (เช่น"$my_error_flag"="1") ซึ่งป้องกันไม่ให้เชลล์จำได้ว่ามันเป็นตัวดำเนินการเลย โปรดอ่านBashFAQ # 17 (ในการจัดกลุ่ม)และ# 31 (ความแตกต่างระหว่างประเภทที่แตกต่างกันในการแสดงออกการทดสอบ) ที่จริงในกรณีนี้มันจะง่ายยิ่งขึ้นที่จะใช้การแสดงออกทางคณิตศาสตร์
Gordon Davisson

7
-aและ-oได้รับการพิจารณาว่าล้าสมัยโดยข้อกำหนด POSIX ; ใช้การทดสอบแยกต่างหากรวมกับ||ในการปรับปรุง
chepner

1
ไม่จำเป็นต้องจัดกลุ่มโดยใช้ subshells โดยปกติแล้วการจัดกลุ่มการใช้{}ควรเป็นไปได้เช่นกัน
phk

1
เพื่อเพิ่มความคิดเห็นของ phk ข้างต้น () กำลังเปิดตัว subshells ใน bash ซึ่งสามารถมีเอฟเฟกต์แบบละเอียด (อาจไม่ต้องการ) ได้ทุกประเภท
brett

70

คุณสามารถใช้อย่างใดอย่างหนึ่ง[[หรือ((คำหลัก เมื่อคุณใช้[[คำสำคัญคุณจะต้องใช้ตัวดำเนินการสตริงเช่น-eq, -lt. ผมคิดว่า((เป็นที่ต้องการมากที่สุดสำหรับการคำนวณเพราะคุณโดยตรงสามารถใช้ประกอบการเช่น==, และ<>

การใช้[[ตัวดำเนินการ

a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
     echo "Error"
else
     echo "No Error"
fi

การใช้((ตัวดำเนินการ

a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
     echo "Error"
else
     echo "No Error"
fi

ห้ามใช้-aหรือ-oตัวดำเนินการเนื่องจากไม่ใช่พกพา


8

โปรดลองทำตาม

if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
    echo "WORKING"
else
    echo "Out of range!"

2
( ... )สร้าง subshells - ผลกระทบต่อประสิทธิภาพมากมายไม่เป็นประโยชน์
Charles Duffy

4
ใช้{ ...; }สำหรับการจัดกลุ่มโดยไม่มีการสร้างเชลล์ย่อย
Charles Duffy

1

คุณสามารถรับแรงบันดาลใจจากการอ่านentrypoint.sh สคริปต์เขียนโดยผู้มีส่วนร่วมจาก MySQL ซึ่งตรวจสอบว่ามีการตั้งค่าตัวแปรที่ระบุหรือไม่

ตามที่สคริปต์แสดงคุณสามารถไพพ์ด้วย-aเช่น:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi

1
-aถูกทำเครื่องหมายเป็นล้าสมัยในเวอร์ชันปัจจุบันของtestมาตรฐานPOSIX ; ดูOBเครื่องหมายที่pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html ใช้[ -z "$FOO" ] && [ -z "$BAR" ]เพื่อให้มีรหัสที่เชื่อถือได้มากขึ้น
Charles Duffy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.