Các toán tử &&
và ||
toán tử không phải là sự thay thế nội tuyến chính xác cho if-then-other. Mặc dù nếu được sử dụng cẩn thận, chúng có thể thực hiện được nhiều điều tương tự.
Một bài kiểm tra đơn giản và rõ ràng ...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
Tuy nhiên, cố gắng thêm nhiều thử nghiệm có thể mang lại kết quả không mong muốn ...
[[ A == A ]] && echo TRUE || echo FALSE # TRUE (as expected)
[[ A == B ]] && echo TRUE || echo FALSE # FALSE (as expected)
[[ A == A ]] || echo FALSE && echo TRUE # TRUE (as expected)
[[ A == B ]] || echo FALSE && echo TRUE # FALSE TRUE (huh?)
Tại sao cả hai FALSE và TRUE lặp lại?
Điều đang xảy ra ở đây là chúng tôi đã không nhận ra điều đó &&
và ||
là các toán tử quá tải hoạt động khác nhau trong các khung kiểm tra có điều kiện [[ ]]
so với các hoạt động trong danh sách AND và OR (thực thi có điều kiện) mà chúng tôi có ở đây.
Từ trang bash (chỉnh sửa) ...
Danh sách
Danh sách là một chuỗi gồm một hoặc nhiều đường ống được phân tách bởi một trong các toán tử;, &, &&, hoặc và được kết thúc tùy ý bởi một trong ;, &, hoặc. Trong số các toán tử danh sách này, && và có quyền ưu tiên như nhau, theo sau là; và &, có quyền ưu tiên như nhau.
Một chuỗi gồm một hoặc nhiều dòng mới có thể xuất hiện trong danh sách thay vì dấu chấm phẩy để phân định các lệnh.
Nếu một lệnh bị chấm dứt bởi toán tử điều khiển &, shell sẽ thực thi lệnh trong nền trong một lớp con. Shell không chờ lệnh kết thúc và trạng thái trả về là 0. Các lệnh được phân tách bằng a; được thực hiện tuần tự; Shell chờ lần lượt từng lệnh kết thúc. Trạng thái trả về là trạng thái thoát của lệnh cuối cùng được thực thi.
Danh sách AND và OR là các chuỗi của một trong nhiều đường ống được phân tách bằng các toán tử điều khiển && và tương ứng. Danh sách AND và OR được thực hiện với tính kết hợp trái.
Danh sách AND có dạng ...
command1 && command2
Command2 được thực thi nếu và chỉ khi, lệnh1 trả về trạng thái thoát bằng không.
Danh sách OR có dạng ...
command1 ││ command2
Command2 được thực thi khi và chỉ khi lệnh1 trả về trạng thái thoát khác không.
Trạng thái trả về của danh sách AND và OR là trạng thái thoát của lệnh cuối cùng được thực thi trong danh sách.
Trở lại ví dụ cuối cùng của chúng tôi ...
[[ A == B ]] || echo FALSE && echo TRUE
[[ A == B ]] is false
|| Does NOT mean OR! It means...
'execute next command if last command return code(rc) was false'
echo FALSE The 'echo' command rc is always true
(i.e. it successfully echoed the word "FALSE")
&& Execute next command if last command rc was true
echo TRUE Since the 'echo FALSE' rc was true, then echo "TRUE"
Được chứ. Nếu đó là chính xác, thì tại sao ví dụ tiếp theo lại lặp lại bất cứ điều gì?
[[ A == A ]] || echo FALSE && echo TRUE
[[ A == A ]] is true
|| execute next command if last command rc was false.
echo FALSE Since last rc was true, shouldn't it have stopped before this?
Nope. Instead, it skips the 'echo FALSE', does not even try to
execute it, and continues looking for a `&&` clause.
&& ... which it finds here
echo TRUE ... so, since `[[ A == A ]]` is true, then it echos "TRUE"
Nguy cơ lỗi logic khi sử dụng nhiều hơn một &&
hoặc ||
trong danh sách lệnh là khá cao.
khuyến nghị
Một &&
hoặc ||
một danh sách lệnh hoạt động như mong đợi vì vậy khá an toàn. Nếu đó là một tình huống mà bạn không cần một mệnh đề khác, một cái gì đó như sau có thể rõ ràng hơn để làm theo (các dấu ngoặc nhọn được yêu cầu để nhóm 2 lệnh cuối cùng) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
Nhiều toán tử &&
và ||
toán tử, trong đó mỗi lệnh ngoại trừ lệnh cuối cùng là một thử nghiệm (tức là bên trong ngoặc [[ ]]
), thường cũng an toàn vì tất cả trừ toán tử cuối cùng hoạt động như mong đợi. Toán tử cuối hoạt động giống như một mệnh đề then
hoặc else
.
&&
và||
shellcmd1 && cmd2 || cmd3
có cùng mức ưu tiên, thì&&
in((...))
và[[...]]
có quyền ưu tiên hơn||
(((a || b && c))
is((a || (b && c)))
). Tương tự với-a
/-o
trongtest
/[
vàfind
và&
/|
trongexpr
.