ดูเหมือนว่ามีบางคนเข้าใจผิดเกี่ยวกับ Bash builtin true
และที่เฉพาะเจาะจงมากขึ้นเกี่ยวกับวิธีที่ Bash ขยายและตีความนิพจน์ภายในวงเล็บ
รหัสในคำตอบของ mikuนั้นไม่มีอะไรเกี่ยวข้องกับ Bash builtin true
หรือ/bin/true
อย่างใดtrue
อย่างหนึ่ง ในกรณีtrue
นี้ไม่มีอะไรมากไปกว่าสตริงอักขระแบบง่าย ๆ และไม่มีการเรียกtrue
คำสั่ง / บิลด์อินใด ๆ เลยไม่ว่าจะเป็นการกำหนดตัวแปรหรือการประเมินนิพจน์เงื่อนไข
รหัสต่อไปนี้เป็นหน้าที่เหมือนกับรหัสในคำตอบของ miku:
the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
echo 'Be careful not to fall off!'
fi
ข้อแตกต่างเพียงอย่างเดียวที่นี่คือการเปรียบเทียบอักขระสี่ตัวคือ 'y', 'e', 'a' และ 'h' แทน 't', 'r', 'u' และ 'e' แค่นั้นแหละ. มีความพยายามไม่ทำเพื่อเรียกคำสั่งหรือการ builtin ชื่อเป็นyeah
และไม่มี (ในตัวอย่างของ Miku) เรียงลำดับใด ๆ true
ของการจัดการพิเศษที่เกิดขึ้นเมื่อทุบตีแยกโทเค็น มันเป็นเพียงแค่สตริงและหนึ่งในนั้น
Update (2014-02-19):หลังจากติดตามลิงก์ในคำตอบของ miku ตอนนี้ฉันเห็นว่าความสับสนมาจากไหน คำตอบของ Miku ใช้เครื่องหมายวงเล็บเดียว แต่ข้อมูลโค้ดที่เขาลิงก์ไปนั้นไม่ได้ใช้วงเล็บ มันเป็นเพียง:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Be careful not to fall off!'
fi
ตัวอย่างโค้ดทั้งสองจะทำงานในลักษณะเดียวกัน แต่วงเล็บจะเปลี่ยนสิ่งที่เกิดขึ้นภายใต้ประทุนอย่างสมบูรณ์
นี่คือสิ่งที่ Bash ทำในแต่ละกรณี:
ไม่มีวงเล็บ:
- ขยายตัวแปรสตริง
$the_world_is_flat
"true"
- พยายามแยกสตริง
"true"
เป็นคำสั่ง
- ค้นหาและเรียกใช้
true
คำสั่ง (ทั้งในตัวหรือ/bin/true
ขึ้นอยู่กับรุ่น Bash)
- เปรียบเทียบรหัสทางออกของ
true
คำสั่ง (ซึ่งเป็น 0 เสมอ) กับ 0 เรียกคืนว่าในเชลล์ส่วนใหญ่รหัสทางออก 0 หมายถึงความสำเร็จและสิ่งอื่น ๆ บ่งชี้ความล้มเหลว
- เนื่องจากรหัสออกเป็น 0 (สำเร็จ) ให้รันประโยค
if
ของthen
คำสั่ง
วงเล็บ:
- ขยายตัวแปรสตริง
$the_world_is_flat
"true"
string1 = string2
แยกนิพจน์เงื่อนไขในขณะนี้อย่างเต็มที่ขยายตัวซึ่งเป็นของแบบฟอร์ม =
ผู้ประกอบการคือการทุบตีของการเปรียบเทียบสตริงประกอบการ ดังนั้น...
- ทำเปรียบเทียบสตริงและ
"true"
"true"
- ใช่ทั้งสองสายเหมือนกันดังนั้นค่าของเงื่อนไขเป็นจริง
- ดำเนินการ
if
คำสั่งของthen
ประโยค
รหัส no-brackets ทำงานได้เนื่องจากtrue
คำสั่งส่งคืนรหัสออกเป็น 0 ซึ่งบ่งชี้ความสำเร็จ รหัสวงเล็บทำงานเพราะค่าของ$the_world_is_flat
เป็นเหมือนตัวอักษรสตริงที่ด้านขวาของtrue
=
เพียงขับรถกลับบ้านให้พิจารณาโค้ดสองตัวอย่างต่อไปนี้:
รหัสนี้ (หากทำงานด้วยสิทธิ์พิเศษระดับราก) จะรีบูตคอมพิวเตอร์ของคุณ:
var=reboot
if $var; then
echo 'Muahahaha! You are going down!'
fi
รหัสนี้แค่พิมพ์ "ลองดี" คำสั่ง reboot ไม่ได้ถูกเรียก
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
Update (2014-04-14)เพื่อตอบคำถามในความคิดเห็นเกี่ยวกับความแตกต่างระหว่าง=
และ==
: AFAIK ไม่มีความแตกต่าง ==
ประกอบเป็นคำพ้องทุบตีที่เฉพาะเจาะจงสำหรับ=
, และเท่าที่ผมเคยเห็นพวกเขาทำงานเหมือนกันในทุกบริบท
อย่างไรก็ตามโปรดทราบว่าฉันกำลังพูดถึงตัวดำเนินการเปรียบเทียบ=
และ==
สตริงโดยเฉพาะที่ใช้ในการทดสอบ[ ]
หรือ [[ ]]
ฉันไม่ได้แนะนำสิ่งนั้น=
และ==
สามารถใช้แทนกันได้ทุกที่ในการทุบตี
ตัวอย่างเช่นคุณไม่สามารถกำหนดค่าตัวแปรได้==
อย่างชัดเจนเช่นvar=="foo"
(ในทางเทคนิคคุณสามารถทำสิ่งนี้ได้ แต่ค่าvar
จะเป็น"=foo"
เพราะ Bash ไม่เห็น==
ผู้ประกอบการที่นี่เห็นผู้ดำเนินการ=
(ที่ได้รับมอบหมาย) ตามด้วย ค่าตัวอักษร="foo"
ซึ่งเพิ่งจะกลายเป็น"=foo"
)
นอกจากนี้แม้ว่า=
และ==
สามารถใช้แทนกันคุณควรเก็บไว้ในใจว่าวิธีการที่ทำงานการทดสอบไม่ขึ้นอยู่กับว่าคุณกำลังใช้ภายใน[ ]
หรือ[[ ]]
และยังหรือไม่ว่าตัวถูกดำเนินการที่มีการอ้าง คุณสามารถอ่านเพิ่มเติมเกี่ยวกับสิ่งนั้นได้ในคู่มือการใช้สคริปต์การทุบตีขั้นสูง: 7.3 ตัวดำเนินการเปรียบเทียบอื่น ๆ (เลื่อนลงไปที่การอภิปราย=
และ==
)
true
และfalse
ในบริบทของตัวอย่างส่วนใหญ่ที่อยู่ด้านล่างเป็นเพียงสตริงธรรมดาไม่bash built-ins
!!! โปรดอ่านคำตอบของ Mike Holt ด้านล่าง (นี่คือตัวอย่างหนึ่งที่คำตอบที่ได้รับการโหวตอย่างสูงและได้รับการยอมรับคือ IMHO ทำให้เกิดความสับสนและเงาเนื้อหาที่ลึกซึ้งในคำตอบที่ได้รับการโหวตน้อยกว่า)