ทำไมในขณะที่ [0] เข้าสู่วงวนไม่สิ้นสุด


23

while [ 1 ]ผมเห็นพฤติกรรมเดียวกันสำหรับวงด้านล่างเป็นห่วงด้วย เหตุผลที่เป็นเช่นนั้น?

while [ 0 ]; do
    echo "hello"
done

คำตอบ:


33

วงเล็บเดี่ยวในเปลือกเป็นคำพ้องสำหรับtest(ทั้งคำสั่งที่แยกต่างหากหรือเปลือกในตัว) ดังนั้นหมายความว่าสิ่งเดียวกับ[ 0 ] สำหรับทำการเปรียบเทียบและทดสอบคุณสมบัติของไฟล์ดังที่คุณสามารถอ่านได้ใน manpage ของมัน เมื่อไม่ได้รับนิพจน์ที่ดูเหมือนการเปรียบเทียบการทดสอบไฟล์หรือการดำเนินการอื่นที่สามารถทำได้มันจะทำการทดสอบแทนหากมีอาร์กิวเมนต์และสตริงว่างเปล่า ค่าหรือมีปัจจัยการผลิตที่เหมาะสมจริงๆสำหรับการทดสอบและเป็นสายไม่ว่างเปล่าทดสอบก็ประสบความสำเร็จและห่วงขณะที่ของคุณตลอดไปลูปtest 0test01

คุณอาจต้องการลองแทน

while false; do
  echo "hello"
done

อาจจะเปลี่ยนด้วยfalse trueหรืออาจเป็นสิ่งที่คุณต้องการใช้(( )):

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

ซึ่งจะทำตัวเหมือนภาษาส่วนใหญ่โดยที่ 0 หมายถึงความล้มเหลว / เท็จและ 1 หมายถึงความสำเร็จ / จริง


1
Re: "เมื่อไม่ได้รับนิพจน์ที่ดูเหมือนการเปรียบเทียบการทดสอบไฟล์หรือการดำเนินการอย่างอื่นที่ทำได้ก็ทำได้สำเร็จ": ฉันไม่คิดว่าจะเป็นวิธีที่ดี หลังจากที่ทุกคน[ ](ที่มีข้อโต้แย้งไม่ได้) และ[ "" ](ที่มีข้อโต้แย้งที่ว่างเปล่าเดี่ยว) จะไม่ประสบความสำเร็จ
ruakh

3
ตามที่ @ruakh อธิบายว่าคำสั่งนี้ผิด: เมื่อไม่ได้รับนิพจน์ที่ดูเหมือนการเปรียบเทียบการทดสอบไฟล์หรือการดำเนินการอื่นอย่างใดอย่างหนึ่งที่สามารถทำได้ก็จะประสบความสำเร็จ อาร์กิวเมนต์เดี่ยวใด ๆ ในการทดสอบ (อาร์กิวเมนต์เดี่ยวใด ๆ ภายในวงเล็บเหลี่ยม) ถือเป็น TRUE หากอาร์กิวเมนต์ไม่ใช่สตริงว่างและทั้งคู่0และ1ไม่ใช่สตริงว่าง โปรแกรมเมอร์เชลล์ใหม่มักจะเขียนif [ 1=2 ]แทนif [ 1 = 2 ]และสงสัยว่าทำไมอดีตเป็นจริงเสมอ มันเป็นความจริงเพราะมันเป็นอาร์กิวเมนต์เดียวและไม่ได้เป็นสตริงที่ว่างเปล่า
Ian D. Allen

จุดดีฉันได้ทำการแก้ไข
wingedsubmariner

10

ค่า 0 ที่นี่ไม่ได้ทำหน้าที่เป็นค่าคงที่ตัวเลข แต่เป็นสตริงอักขระ การทดสอบเหล่านี้ทั้งหมดเทียบเท่าในผลของการสร้างสถานะการเลิกจ้างที่ประสบความสำเร็จ:

[ A ]
[ "XYZ" ]
[ 0 ]

สิ่งเหล่านี้สร้างสถานะการเลิกจ้างที่ล้มเหลว:

[ ]
[ "" ]

มีอาร์กิวเมนต์ที่ไม่ว่างซึ่งประเมินค่าเป็นตรรกะจริง สิ่งนี้อนุญาตให้คุณทำสิ่งต่าง ๆ เช่น:

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

ตัวแปรUNDER_NUCLEAR_ATTACKถูกตั้งค่าเป็นค่าที่ไม่ใช่ช่องว่างใด ๆ เพื่อระบุความจริงหรือไม่ได้ตั้งค่าหรือว่างเปล่าเพื่อระบุว่าเป็นเท็จ

เราสามารถใช้!โอเปอเรเตอร์เพื่อย้อนกลับตรรกะ:

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

ในการประเมินสภาพที่เป็นตัวเลขคุณต้องใช้ตัวดำเนินการทดสอบตัวเลข:

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

หากAและBมีสตริงที่ดูเหมือนเลขจำนวนเต็มทศนิยมพวกเขาจะถูกเปรียบเทียบเช่นตัวเลขและถ้าAมากกว่าBนั้นลูปจะดำเนินการ ดังนั้นสมมติว่าUNDER_NUCLEAR_ATTACKไม่ใช่บูลีนแบบสตริงที่ว่างหรือไม่ว่างเปล่า แต่จริงๆแล้วบูลีนตัวเลขที่เป็น0(เท็จ) หรือค่าอื่น ๆ (จริง) ในกรณีนั้นเราจะเขียนแบบทดสอบนี้:

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

-1

ถ้า / จากนั้นสร้างการทดสอบว่าสถานะทางออกของรายการคำสั่งเป็น 0 (ตั้งแต่ 0 หมายถึง "สำเร็จ" โดยการประชุม UNIX) และถ้าเป็นเช่นนั้นดำเนินการหนึ่งคำสั่งหรือมากกว่า

ในระยะสั้นคุณจะส่งคืนผลการทดสอบเป็นศูนย์

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


5
ใช่ แต่ไม่ใช่เพราะเหตุผลที่คุณคิด หาก[ได้รับเพียงหนึ่งอาร์กิวเมนต์ (ยกเว้น]แน่นอน) จะมีสถานะเป็นศูนย์ถ้าอาร์กิวเมนต์นั้นไม่ว่างเปล่าไม่ใช่ศูนย์ถ้าเป็น ดังนั้นสำหรับตัวอย่างเช่นยังจะกลับรหัสจบการทำงาน[ 1 ] 0
เควิน

-1

ค่า 0 ถูกพิจารณาว่าเป็นจริงสำหรับ while loop ดังนั้นเงื่อนไขสำหรับ while loop จึงเป็นจริงและดังนั้นจึงมีความต่อเนื่องในการแสดงลูปไม่สิ้นสุด เป็นจริงถ้าเราแทนที่ 0 ด้วย 1 เป็นจำนวนเต็มใด ๆ ที่เราเขียนระหว่างเงื่อนไขมันจะกลับมาจริง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.