Cú pháp của một điều kiện phức tạp trong shell là gì?


10

Nếu muốn thể hiện bài kiểm tra sau trong shell (sh):

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

Cho đến nay, điều tốt nhất tôi có thể viết là thế này:

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

Tôi không biết cách ghép && và || với quyền ưu tiên chính xác. Googling đã không cho tôi bất kỳ câu trả lời nào (hướng dẫn chỉ đưa ra các ví dụ cơ bản, nếu có)

Cú pháp để kết hợp cả hai nếu thành một là gì?


1
Bất kỳ lý do để không sử dụng ksh? Sau đó, mã ban đầu của bạn sẽ chỉ cần thêm một cặp dấu ngoặc đơn:if (( a == 1 && ( b == 1 || b == 2 ))); then :; fi
manatwork

Câu trả lời:


14

Lưu ý rằng [[ ]]không có trong Bourne hoặc POSIX sh. Đối với shcú pháp đúng , có một số cách để làm điều này.

Chỉ sử dụng một [ ]cặp

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

hoặc Tránh POSIX -a-ocác tùy chọn 1

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

1 Một lý do để tránh -a-olà tính di động tối đa - không phải tất cả testhoặc [triển khai có thể xử lý hơn 4 đối số, đó chính xác là những gì bạn nhận được nếu bạn chuỗi biểu thức với -a-o\( \).


Kịch bản của tôi có #! / bin / sh shebang và shell mặc định là ksh . Tại sao sh sẽ không được sử dụng?
Offifyo

2
@ Offerirmo Nếu bạn khai báo tập lệnh của mình là /bin/sh, việc viết tập lệnh bằng các tính năng không có trong đó là không chính xác sh. Bạn nên biết rằng kshKHÔNG phải sh, mà là một superset của sh. Nếu bạn mang tập lệnh ksh-but-khai-as-as của shmình đến một hệ thống shkhông phải là liên kết tượng trưng ksh, nó có thể bị hỏng. Bạn có thể tránh vấn đề đó bằng cách đảm bảo tập lệnh của bạn khớp với khai báo.
jw013

Tôi nghĩ rằng thiết lập / bin / sh là shebang sẽ làm cho các tập lệnh của tôi được gọi thông qua / bin / sh . Bạn có nghĩa là shell mặc định của tôi (ksh) bỏ qua shebang và giải thích nó trực tiếp?
Offifyo

@ Offerirmo Bạn đã đúng: một shebang /bin/shsẽ gọi /bin/sh. Vấn đề là /bin/shkhông chấp nhận [[. Bạn không thể sử dụng [[hoặc sử dụng shell chấp nhận [[, ví dụ kshnhư shebang của bạn.
jw013

2
Vấn đề không phải là nhiều đến mức -a/ -okhông được hỗ trợ bởi một số triển khai nhưng nó không đáng tin cậy cho các đối số tùy ý. Like [ "$a" = "$b" -o "$b" = "$c" ]sẽ thất bại đối với các giá trị $alike !với nhiều [triển khai.
Stéphane Chazelas

2

Tôi đã thử một số cú pháp và thấy rằng

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

đang làm việc.


1
cái này hoạt động cho phiên bản bash trên 4.
Nikhil Mulley

2

Một cách tiếp cận POSIX khác:

if [ "$((a == 1 && ( b == 1 || b == 2 )))" -ne 0 ]; then
  ...
fi

0

Cách đúng để làm điều đó chỉ với một shell:

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

Giải trình:

testở đây phục vụ như dấu ngoặc đơn và -onhư logic hoặc. Nếu bạn logic và bên trong "dấu ngoặc đơn" bạn sẽ sử dụng -a.

Thêm vào đó có thể được tìm thấy ở đây

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.