ตัวดำเนินการ&&
และ||
ตัวดำเนินการไม่ใช่การแทนที่แบบอินไลน์ที่แน่นอนสำหรับ if-then-else แม้ว่าจะใช้อย่างระมัดระวัง แต่ก็สามารถทำสิ่งเดียวกันให้สำเร็จได้
การทดสอบเพียงครั้งเดียวนั้นตรงไปตรงมาและชัดเจน ...
[[ A == A ]] && echo TRUE # TRUE
[[ A == B ]] && echo TRUE #
[[ A == A ]] || echo FALSE #
[[ A == B ]] || echo FALSE # FALSE
อย่างไรก็ตามการพยายามเพิ่มการทดสอบหลายครั้งอาจให้ผลลัพธ์ที่ไม่คาดคิด ...
[[ 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?)
ทำไมทั้ง FALSE และ TRUE จึงถูกสะท้อน
สิ่งที่เกิดขึ้นที่นี่คือเราไม่ได้ตระหนัก&&
และ||
มีตัวดำเนินการโอเวอร์โหลดที่ทำหน้าที่แตกต่างกันในวงเล็บทดสอบตามเงื่อนไข[[ ]]
มากกว่าที่พวกเขาทำในรายการ AND และ OR (ดำเนินการตามเงื่อนไข) ที่เรามีที่นี่
จาก manpage ทุบตี (แก้ไข) ...
รายการ
รายการคือลำดับของหนึ่งหรือมากกว่าหนึ่งท่อคั่นด้วยหนึ่งในผู้ประกอบการ; &, & &, หรือ││และยกเลิกทางเลือกโดยหนึ่งใน; &, หรือ ของโอเปอเรเตอร์รายการเหล่านี้ && และ││มีลำดับความสำคัญเท่ากันตามด้วย; และ & ซึ่งมีความสำคัญเท่ากัน
ลำดับของการขึ้นบรรทัดใหม่อย่างน้อยหนึ่งรายการอาจปรากฏในรายการแทนที่จะใช้เครื่องหมายอัฒภาคเพื่อคั่นคำสั่ง
หากคำสั่งถูกยกเลิกโดยผู้ควบคุมเครื่อง & เปลือกจะดำเนินการคำสั่งในพื้นหลังเป็นเชลล์ย่อย เชลล์ไม่รอให้คำสั่งเสร็จสิ้นและสถานะการส่งคืนคือ 0 คำสั่งคั่นด้วย; ถูกดำเนินการตามลำดับ เชลล์รอให้แต่ละคำสั่งสิ้นสุดลง สถานะการส่งคืนคือสถานะการออกของคำสั่งสุดท้ายที่ดำเนินการ
รายการ AND และ OR เป็นลำดับของหนึ่งในท่อที่คั่นด้วยตัวดำเนินการควบคุม && และ││ตามลำดับ รายการ AND และ OR ถูกดำเนินการด้วยการเชื่อมโยงด้านซ้าย
รายการ AND มีรูปแบบ ...
command1 && command2
Command2 ถูกดำเนินการถ้าและถ้า command1 ส่งคืนสถานะการออกเป็นศูนย์
รายการ OR มีรูปแบบ ...
command1 ││ command2
Command2 จะถูกดำเนินการถ้าหาก command1 ส่งคืนสถานะการออกที่ไม่ใช่ศูนย์
สถานะการส่งคืนของรายการ AND และ OR คือสถานะการออกของคำสั่งสุดท้ายที่ดำเนินการในรายการ
กลับไปเป็นตัวอย่างสุดท้ายของเรา ...
[[ 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"
ถูก หากถูกต้องแล้วทำไมตัวอย่างถัดไปสุดท้ายจึงสะท้อนสิ่งใดเลย
[[ 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"
ความเสี่ยงของข้อผิดพลาดทางตรรกะเมื่อใช้มากกว่าหนึ่งรายการ&&
หรือ||
ในรายการคำสั่งนั้นค่อนข้างสูง
ข้อเสนอแนะ
รายการคำสั่งเดียว&&
หรือ||
ในรายการทำงานตามที่คาดไว้จึงค่อนข้างปลอดภัย หากเป็นสถานการณ์ที่คุณไม่จำเป็นต้องใช้ประโยคอื่น ๆ สิ่งต่อไปนี้สามารถทำให้ชัดเจนขึ้นเพื่อติดตาม (จำเป็นต้องใช้วงเล็บปีกกาเพื่อจัดกลุ่มคำสั่ง 2 รายการสุดท้าย) ...
[[ $1 == --help ]] && { echo "$HELP"; exit; }
หลาย&&
และ||
ผู้ประกอบการที่แต่ละคำสั่งยกเว้นสำหรับที่ผ่านมาคือการทดสอบ (เช่นวงเล็บภายใน[[ ]]
) มักจะยังปลอดภัยทั้งหมด แต่ประพฤติประกอบการที่ผ่านมาตามที่คาดไว้ ตัวดำเนินการสุดท้ายทำหน้าที่เหมือนthen
หรือelse
ประโยคมากกว่า
&&
และ||
เชลล์cmd1 && cmd2 || cmd3
มีความสำคัญเท่ากัน&&
ใน((...))
และ[[...]]
มีความสำคัญมากกว่า||
(((a || b && c))
คือ((a || (b && c)))
) กันไปสำหรับ-a
/-o
ในtest
/[
และfind
และ&
/ ใน|
expr