Mengapa sementara [0] masuk ke loop tak terbatas?

23

Saya melihat perilaku yang sama untuk loop di bawah ini sebagai loop dengan while [ 1 ]. Kenapa begitu?

while [ 0 ]; do
    echo "hello"
done
pengguna13107
sumber

Jawaban:

33

Kurung kotak tunggal dalam shell adalah sinonim untuk test(baik perintah terpisah atau built-in shell), jadi [ 0 ]artinya sama dengan test 0. testadalah untuk melakukan perbandingan dan menguji atribut file, seperti yang dapat Anda baca di halaman manualnya. Ketika tidak diberi ekspresi yang terlihat seperti perbandingan, uji file, atau salah satu operasi lain yang bisa dilakukan, itu akan menguji apakah argumen ada dan string yang tidak kosong. Baik 0atau 1benar-benar input yang tepat untuk pengujian, dan sebagai tes string non-kosong hanya berhasil dan loop sementara Anda loop selamanya.

Anda mungkin ingin mencoba saja

while false; do
  echo "hello"
done

mungkin diganti falsedengan true. Atau mungkin yang Anda inginkan adalah menggunakan (( )):

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

Yang akan berperilaku seperti kebanyakan bahasa, di mana 0 berarti gagal / salah dan 1 berarti sukses / benar.

wingedsubmariner
sumber
1
Re: "Ketika tidak diberi ekspresi yang terlihat seperti perbandingan, uji file, atau salah satu operasi lain yang dapat dilakukan, itu hanya berhasil": Saya tidak berpikir itu cara yang baik untuk menjelaskannya. Lagi pula, [ ](tanpa argumen) dan [ "" ](dengan argumen kosong tunggal) tidak berhasil.
ruakh
3
Seperti yang dijelaskan oleh @ruakh, pernyataan ini salah: Ketika tidak diberi ekspresi yang terlihat seperti perbandingan, pengujian file, atau salah satu dari operasi lain yang dapat dilakukan, itu hanya berhasil. Argumen tunggal untuk menguji (argumen apa pun di dalam tanda kurung siku) dianggap BENAR jika argumen tersebut bukan string kosong, dan keduanya 0dan 1bukan string kosong. Pemrogram shell baru sering menulis if [ 1=2 ]alih-alih if [ 1 = 2 ]dan bertanya-tanya mengapa yang pertama selalu benar. Itu benar karena itu adalah argumen tunggal dan bukan string kosong.
Ian D. Allen
Poin bagus, saya sudah membuat koreksi.
wingedsubmariner
10

Nilai 0 di sini tidak bertindak sebagai konstanta numerik, tetapi sebagai string karakter. Semua tes ini setara dalam efeknya menghasilkan status terminasi yang sukses:

[ A ]
[ "XYZ" ]
[ 0 ]

ini menghasilkan status pemutusan yang gagal:

[ ]
[ "" ]

ada argumen non-kosong, yang mengevaluasi ke true logis. Ini memungkinkan Anda melakukan hal-hal seperti:

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

Variabel UNDER_NUCLEAR_ATTACKdiatur ke nilai non-kosong untuk menunjukkan benar, atau tidak disetel atau kosong untuk menunjukkan salah.

Kita dapat menerapkan !operator untuk membalik logika:

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

Untuk mengevaluasi kondisi numerik, Anda harus menggunakan operator tes numerik:

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

Jika Adan Bberisi string yang terlihat seperti bilangan bulat desimal, mereka dibandingkan seperti angka, dan jika Alebih besar dari B, loop dijalankan. Jadi anggaplah itu UNDER_NUCLEAR_ATTACKbukan boolean tipe string yang kosong atau tidak kosong, tetapi sebenarnya boolean numerik yang baik 0(salah) atau beberapa nilai lainnya (benar). Dalam hal ini, kami akan menulis tes seperti ini:

 if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
Kaz
sumber
-1

Jika / kemudian membangun tes apakah status keluar dari daftar perintah adalah 0 (karena 0 berarti "sukses" oleh konvensi UNIX), dan jika demikian, jalankan satu atau lebih perintah.

Singkatnya, Anda mengembalikan hasil tes nol.

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

Stephan
sumber
5
Ya, tetapi bukan karena alasan yang tampaknya Anda pikirkan. Jika [hanya mendapat satu argumen (tidak termasuk ], tentu saja) itu keluar dengan status nol jika argumen tidak kosong, tidak nol jika itu. Jadi, misalnya, [ 1 ]juga akan mengembalikan kode keluar dari 0.
Kevin
-1

Nilai 0 dianggap sebagai true untuk loop sementara karena itu kondisi untuk loop sementara benar dan karena itu terus menerus untuk menunjukkan loop tak terbatas. Benar jika kita mengganti 0 dengan 1, karena setiap bilangan bulat yang kita tulis di antara kondisi itu akan mengembalikan true

Jyoti Minhas
sumber