Bash nếu câu lệnh có nhiều điều kiện đưa ra một lỗi


165

Tôi đang cố gắng viết một tập lệnh sẽ kiểm tra hai cờ lỗi và trong trường hợp một cờ (hoặc cả hai) bị thay đổi, nó sẽ lặp lại - lỗi đã xảy ra. Kịch bản của tôi:

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

Về cơ bản, nó nên là, một cái gì đó cùng:

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

Lỗi tôi nhận được là:

 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'

Là dấu ngoặc của tôi bị rối?



2
Sử dụng dấu ngoặc đơn - ()
AlikElzin-kilaka


3
Theo logic, a==1 or b==2đã bao gồm các trường hợp a==1 and b==2. Kiểm tra riêng cho điều đó là hoàn toàn thừa ở đây.
tripleee

Câu trả lời:


248

Sử dụng -a(cho và) và -o(cho hoặc) hoạt động.

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

Cập nhật

Trên thực tế bạn vẫn có thể sử dụng &&||với các -eqhoạt động. Vì vậy, kịch bản của bạn sẽ như thế này:

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

Mặc dù trong trường hợp của bạn, bạn có thể loại bỏ hai biểu thức cuối cùng và chỉ cần sử dụng một hoặc thao tác như thế này:

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: Không, OR logic là đúng nếu một hoặc cả hai toán hạng của nó là đúng. Bạn đang nghĩ về "độc quyền hoặc" (XOR), điều này đúng nếu chính xác một trong các toán hạng của nó là đúng. (Trên thực tế, có các phiên bản XOR hoạt động trên hơn 2 toán hạng, trong trường hợp đó là đúng nếu một số toán hạng lẻ là đúng.)
Gordon Davisson

4
BTW, các vấn đề trong mã gốc bao gồm việc sử dụng []để nhóm (họ không làm như vậy) và không đặt khoảng trắng xung quanh toán tử (ví dụ "$my_error_flag"="1"), điều này ngăn không cho shell nhận ra nó là toán tử. Vui lòng đọc BashFAQ # 17 (về nhóm)# 31 (về sự khác biệt giữa các loại biểu thức kiểm tra khác nhau) . Trên thực tế, trong trường hợp này, việc sử dụng biểu thức số học sẽ dễ dàng hơn nữa.
Gordon Davisson

7
-a-ođược coi là lỗi thời bởi đặc tả POSIX ; sử dụng các thử nghiệm riêng biệt kết hợp với ||như trong bản cập nhật.
chepner

1
Không cần phải nhóm bằng cách sử dụng các lớp con, thông thường việc phân nhóm bằng cách sử dụng {}cũng có thể.
phk

1
để thêm vào nhận xét của phk ở trên, () đang khởi chạy các chuỗi con trong bash, có thể có tất cả các loại hiệu ứng tinh tế [có thể không mong muốn].
brett

70

Bạn có thể sử dụng [[hoặc ((từ khóa. Khi bạn sử dụng [[từ khóa, bạn phải sử dụng các toán tử chuỗi như -eq, -lt. Tôi nghĩ, ((được ưu tiên nhất cho số học, bởi vì bạn có thể trực tiếp sử dụng các toán tử như ==, <>.

Sử dụng [[toán tử

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

Sử dụng ((toán tử

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

Không sử dụng -ahoặc -ovận hành Vì nó không phải là Portable.


8

Hãy thử làm theo

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
( ... )tạo các subshells - rất nhiều tác động hiệu suất không có lợi ích.
Charles Duffy

4
Sử dụng { ...; }để nhóm mà không tạo ra subshell.
Charles Duffy

1

Bạn có thể lấy cảm hứng bằng cách đọc một entrypoint.sh tập lệnh được viết bởi những người đóng góp từ MySQL để kiểm tra xem các biến đã chỉ định có được đặt hay không.

Như tập lệnh hiển thị, bạn có thể đặt chúng với -a, ví dụ:

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

1
-ađược đánh dấu là lỗi thời trong phiên bản hiện tại của testtiêu chuẩn POSIX ; xem các OBđiểm đánh dấu tại pubs.opengroup.org/onlinepub/9699919799/utilities/test.html . Sử dụng [ -z "$FOO" ] && [ -z "$BAR" ]để có mã đáng tin cậy hơn.
Charles Duffy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.