Tại sao trong khi [0] đi vào vòng lặp vô hạn?


23

Tôi thấy hành vi tương tự cho vòng lặp bên dưới như vòng lặp với while [ 1 ]. Tại sao lại như vậy?

while [ 0 ]; do
    echo "hello"
done

Câu trả lời:


33

Dấu ngoặc đơn trong shell là từ đồng nghĩa với test(lệnh riêng hoặc vỏ được tích hợp sẵn), do đó [ 0 ]có nghĩa tương tự như test 0. testlà để thực hiện so sánh và kiểm tra các thuộc tính của tệp, như bạn có thể đọc trong trang chủ của nó. Khi nó không được đưa ra một biểu thức trông giống như một phép so sánh, kiểm tra tệp hoặc một trong các thao tác khác mà nó có thể thực hiện, thay vào đó, nó sẽ kiểm tra nếu có đối số và một chuỗi không trống. Không 0hoặc 1là đầu vào thực sự thích hợp để kiểm tra, và vì kiểm tra chuỗi không trống chỉ đơn giản là thành công và vòng lặp while của bạn mãi mãi.

Bạn có thể muốn thử thay thế

while false; do
  echo "hello"
done

có thể thay thế falsebằng true. Hoặc có thể những gì bạn muốn là sử dụng (( )):

while (( 0 )); do
  echo "hello"
done

Điều này sẽ hành xử giống như hầu hết các ngôn ngữ, trong đó 0 có nghĩa là thất bại / sai và 1 có nghĩa là thành công / đúng.


1
Re: "Khi nó không được đưa ra một biểu thức giống như so sánh, kiểm tra tệp hoặc một trong những thao tác khác mà nó có thể thực hiện, thì đơn giản là nó thành công": Tôi không nghĩ đó là một cách hay để đặt nó. Rốt cuộc, [ ](không có đối số) và [ "" ](với một đối số trống duy nhất) không thành công.
ruakh

3
Như @ruakh giải thích, tuyên bố này là sai: Khi nó không được đưa ra một biểu thức giống như so sánh, kiểm tra tệp hoặc một trong các hoạt động khác mà nó có thể thực hiện, đơn giản là nó thành công. Bất kỳ đối số nào để kiểm tra (bất kỳ đối số đơn lẻ nào trong dấu ngoặc vuông) đều được coi là TRUE nếu đối số không phải là một chuỗi rỗng và cả hai 01không phải là các chuỗi rỗng. Các lập trình viên shell mới thường viết if [ 1=2 ]thay vì if [ 1 = 2 ]và tự hỏi tại sao cái trước luôn luôn đúng. Điều này đúng bởi vì nó là một đối số duy nhất và không phải là một chuỗi rỗng.
Ian D. Allen

Điểm tốt, tôi đã thực hiện một điều chỉnh.
wingbedubmariner

10

Giá trị 0 ở đây không hoạt động như một hằng số, mà là một chuỗi ký tự. Các xét nghiệm này đều tương đương với hiệu quả của việc tạo ra trạng thái chấm dứt thành công:

[ A ]
[ "XYZ" ]
[ 0 ]

những điều này tạo ra một trạng thái chấm dứt không thành công:

[ ]
[ "" ]

có một đối số không trống, đánh giá là đúng logic. Điều này cho phép bạn làm những việc như:

if [ $UNDER_NUCLEAR_ATTACK ] ; then
  launch-missiles -a $DRY_RUN  # $DRY_RUN set to "-n" during testing
fi

Biến UNDER_NUCLEAR_ATTACKđược đặt thành bất kỳ giá trị không trống nào để chỉ đúng, hoặc không được đặt hoặc trống để biểu thị sai.

Chúng ta có thể áp dụng !toán tử để đảo ngược logic:

[ ! a ]  # fails: a is nonblank so true; and not true is false.
[ ! ]    # succeeds: blank is false, not blank is true.

Để đánh giá một điều kiện số, bạn phải sử dụng các toán tử kiểm tra số:

 while [ $A -gt $B ] ; do ...

Nếu ABchứa các chuỗi trông giống như số nguyên thập phân, chúng được so sánh như số và nếu Alớn hơn B, vòng lặp sẽ thực thi. Vì vậy, giả sử rằng đó UNDER_NUCLEAR_ATTACKkhông phải là một boolean kiểu chuỗi trống hoặc không trống, mà thực sự là một boolean số là 0(sai) hoặc một số giá trị khác (true). Trong trường hợp đó, chúng tôi sẽ viết bài kiểm tra như thế này:

 if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...

-1

Một if / then xây dựng kiểm tra xem trạng thái thoát của danh sách các lệnh là 0 (vì 0 có nghĩa là "thành công" theo quy ước UNIX) và nếu vậy, thực thi một hoặc nhiều lệnh.

Nói tóm lại, bạn đang trả về kết quả kiểm tra bằng không.

http://www.tldp.org/LDP/abs/html/testconstructs.html


5
Có, nhưng không phải vì lý do bạn dường như nghĩ. Nếu [chỉ nhận được một đối số (tất nhiên không bao gồm ]), nó sẽ thoát với trạng thái 0 nếu đối số không trống, khác không nếu nó là. Vì vậy, ví dụ, [ 1 ]cũng sẽ trả về mã thoát của 0.
Kevin

-1

Giá trị 0 được coi là đúng cho vòng lặp while do đó điều kiện cho vòng lặp while là đúng và do đó nó liên tục hiển thị vòng lặp vô hạn. Điều này đúng nếu chúng ta thay 0 bằng 1, vì bất kỳ số nguyên nào chúng ta viết giữa điều kiện nó sẽ trả về true

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.