การใช้ && และ || สับสน ผู้ประกอบการ


93

ฉันอ่านผ่าน/etc/rc.d/init.d/sendmailไฟล์ (ฉันรู้ว่านี่ไม่ค่อยใช้ แต่ฉันกำลังเรียนเพื่อสอบ) และฉันสับสนเล็กน้อยเกี่ยวกับตัวดำเนินการ&&และตัว||ดำเนินการ ฉันอ่านที่พวกเขาสามารถใช้ในงบเช่น:

if [ test1 ] && [ test2 ]; then
     echo "both tests are true"
elif [ test1 ] || [ test2 ]; then
     echo "one test is true"
fi

อย่างไรก็ตามสคริปต์นี้แสดงคำสั่งบรรทัดเดียวเช่น:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE"
[ -f /usr/sbin/sendmail ] || exit 0

สิ่งเหล่านี้ดูเหมือนจะใช้&&และ||โอเปอเรเตอร์เพื่อล้วงเอาการตอบสนองจากการทดสอบ แต่ฉันไม่สามารถขุดเอกสารเกี่ยวกับการใช้งานของผู้ให้บริการเหล่านี้ได้ ใครช่วยอธิบายสิ่งเหล่านี้ได้บ้างในบริบทนี้

คำตอบ:


141

ด้านขวาของ&&จะได้รับการประเมินหากสถานะการออกของด้านซ้ายเป็นศูนย์ (เช่นจริง) ||เป็นสิ่งที่ตรงกันข้าม: มันจะประเมินด้านขวาเฉพาะในกรณีที่สถานะทางออกด้านซ้ายไม่เป็นศูนย์ (เช่นเท็จ)

คุณสามารถพิจารณาว่า[ ... ]เป็นโปรแกรมที่มีค่าส่งคืน ถ้าการทดสอบภายในประเมินค่าเป็นจริงมันจะส่งกลับค่าศูนย์ มันจะส่งกลับค่าที่ไม่ใช่ศูนย์

ตัวอย่าง:

$ false && echo howdy!

$ true && echo howdy!
howdy!
$ true || echo howdy!

$ false || echo howdy!
howdy!

หมายเหตุเพิ่มเติม:

ถ้าคุณทำwhich [คุณอาจเห็นว่า[จริง ๆ แล้วชี้ไปที่โปรแกรม! โดยปกติแล้วมันไม่ได้เป็นสคริปต์ที่ทำงานได้จริง วิ่งtype [เพื่อดูว่าอะไรวิ่งได้จริง หากคุณ wan /bin/[ 1 = 1จะลองใช้โปรแกรมนี้เพียงแค่ให้เส้นทางแบบเต็มเช่นดังนั้น:


6
เมื่อคุณเห็น "X หรือ Y" คุณจะทดสอบ X หากเป็นจริงคุณจะรู้คำตอบของ "X หรือ Y" (จริง) ดังนั้นจึงไม่จำเป็นต้องทดสอบ Y หากเป็นจริงคุณจะไม่รู้ ตอบ "X หรือ Y" ดังนั้นคุณจำเป็นต้องทดสอบ Y เมื่อคุณเห็น "X และ Y" คุณทดสอบ X ถ้ามันเป็นเท็จคุณก็รู้คำตอบของ "X และ Y" (มันเป็นเท็จ) ดังนั้น ไม่จำเป็นต้องทดสอบ Y หาก X เป็นจริงคุณต้องทดสอบ Y เพื่อดูว่า "X และ Y" เป็นจริงหรือไม่
David Schwartz

2
แทนที่จะเป็น "ถ้าด้านซ้ายคืนค่าศูนย์" ฉันจะเขียน "ถ้าสถานะการออกของคำสั่งด้านซ้ายเป็นศูนย์" ผมพบว่า "กลับ" บิตคลุมเครือเป็นส่งออกและสถานะออกทั้งสองจะสามารถถือได้ว่าเป็น "ค่ากลับ"
เกล็น Jackman

ไม่เพียง แต่คุณสามารถ " พิจารณา [ ... ]จะเป็นโปรแกรม" ในหลายกรณีก็คือ มันเป็นเรื่องทั่วไปในไฟล์หรือ/bin/[ /usr/bin/[
LS

5
โปรแกรมเมอร์ C จะพบว่าสิ่งนี้ทำให้เกิดความสับสนอย่างยิ่ง มี 0 หมายถึงเท็จ ... ในขณะที่ shellscripting 0 หมายถึงจริง ... ใจเป่า
Calmarius

หนึ่งที่คุณอาจจะพูดถึงก็คือtestแทนหรือif [และif [และif testดูเหมือนจะสลับกับ[และtestไม่มีการสัมผัสหรือเหตุผลที่ชัดเจน testจะแสดงขึ้นในโอกาสเช่นที่config.site สำหรับ libs ผู้ขายบน Fedora x86_64

59

นี่คือสูตรโกงของฉัน:

  • "A; B" Run A และ B โดยไม่คำนึงถึงความสำเร็จของ A
  • "A&& B" Run B หาก A ประสบความสำเร็จ
  • "A || B" รัน B หาก A ล้มเหลว
  • "A &" รัน A ในพื้นหลัง

มีแคลคูลัสแลมบ์ดาที่น่าสนใจบางส่วนที่เกิดขึ้นที่นี่แสดงให้เห็นในการทำงาน JavaScript (กำหนดตัวแปรตามลำดับ); "ซ้าย (a => b => a)(จริงหรือที่รู้จัก)": "สิทธิ (เท็จ (a => b => b)aka)": ระดับ "A; B" (a => b => (() => b())(a()))"แล้ว" "เป็น && B" "ถ้าได้โดยไม่ต้องอื่น (a => b => a()(() => right)(b))(เมื่อ)" "เป็น || B" "อื่นโดยไม่ได้ถ้า (a => b => a()(b)(() => right))(เว้นแต่)" "a && ข || ค" (a => b => c => (unless(when(a)(b))(c))())"ifThenElse"
Dmitry

1
โปรดทราบว่าใน bash, ซ้ายเป็นสตริง 0 / ว่างอะนาล็อกขวาคล้ายคลึงกันคือทุกอย่างอื่น
Dmitry

28

เพื่อขยายคำตอบของ @ Shawn-j-Goff จากด้านบน&&เป็นตรรกะ AND และ||เป็นตรรกะ OR

ดูส่วนนี้ของคู่มือการใช้สคริปต์การทุบตีขั้นสูง เนื้อหาบางส่วนจากลิงค์สำหรับการอ้างอิงผู้ใช้ดังต่อไปนี้

&& AND

if [ $condition1 ] && [ $condition2 ]
#  Same as:  if [ $condition1 -a $condition2 ]
#  Returns true if both condition1 and condition2 hold true...

if [[ $condition1 && $condition2 ]]    # Also works.
#  Note that && operator not permitted inside brackets
#+ of [ ... ] construct.

|| หรือ

if [ $condition1 ] || [ $condition2 ]
# Same as:  if [ $condition1 -o $condition2 ]
# Returns true if either condition1 or condition2 holds true...

if [[ $condition1 || $condition2 ]]    # Also works.
#  Note that || operator not permitted inside brackets
#+ of a [ ... ] construct.

11

จากประสบการณ์ของฉันฉันใช้ && และ || เพื่อลดคำสั่ง if เป็นบรรทัดเดียว

สมมติว่าเรากำลังมองหาไฟล์ชื่อ /root/Sample.txt ดังนั้นการทำซ้ำแบบดั้งเดิมจะเป็นดังนี้ในเชลล์:

if [ -f /root/Sample.txt ]
then
    echo "file found"
else
    echo "file not found"
fi

6 บรรทัดเหล่านี้สามารถลดเป็นบรรทัดเดียว:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found"

เมื่อรันการวนซ้ำสองสามครั้งเพื่อตั้งค่าตัวแปรหรือเพื่อสร้างไฟล์ ฯลฯ ชีวิตจะง่ายขึ้นและสคริปต์ดูจะสั่นไหวโดยใช้บรรทัดเดียวถ้าฟังก์ชั่นมันเป็นข้อเสียเปรียบเพียงอย่างเดียวคือมันกลายเป็นเรื่องยากขึ้นเล็กน้อยในการใช้หลายคำสั่ง คุณสามารถใช้ประโยชน์จากฟังก์ชั่น


ที่นี่หนาว. แจ้งเตือนฉันด้วยรหัส objc (a == b)? val = 1: val = 2;
GeneCode

ฉันจะใช้คำสั่งนี้เมื่อฉันต้องการเรียกใช้กระบวนการในพื้นหลังด้วย "&" ได้อย่างไร? ฉันพบข้อผิดพลาดทางไวยากรณ์สำหรับ./someScript.sh & && echo 'ok' || echo 'ko'
Katie

4

มีความคิดเรื่อง "การตัดสั้น"

เมื่อ(expr1 && expr2)ได้รับการประเมิน - expr2ถูกประเมินเมื่อexp1ประเมินเป็น "จริง" เท่านั้น นี่เป็นเพราะทั้งสองexpr1และexpr2จะต้องเป็นจริงสำหรับ(expr1 && expr2)การเป็นจริง หากexpr1ประเมินเป็น "false" expr2จะไม่ถูกประเมิน (ทางลัด) เพราะ(expr1 && expr2)มีอยู่แล้ว "flase"

ลองต่อไปนี้ - สันนิษฐานว่าF1มีไฟล์ & ไฟล์F2ไม่อยู่:

( [ -s F1 ] && echo "File Exists" )  # will print "File Exists" - no short cut
( [ -s F2 ] && echo "File Exists" )  # will NOT print "File Exists" - short cut

ในทำนองเดียวกันสำหรับ||(หรือ) - แต่การตัดสั้นกลับด้าน


5
ตรรกะมักจะเรียกว่า "การลัดวงจร" ฉันไม่เคยเห็นวลี "shortcut" ที่ใช้ ฉันพูดถึงสิ่งนี้เพื่อช่วยในการค้นหาข้อมูลอ้างอิง
LS

-1

ตัวอย่างในคำตอบของ Shawn J. Goff นั้นถูกต้อง แต่คำอธิบายเป็นวิธีอื่น โปรดตรวจสอบ:

ทางด้านขวาของ && จะได้รับการประเมินหากสถานะทางออกของด้านซ้ายเป็น NONZERO || ตรงกันข้าม: ระบบจะประเมินด้านขวาหากสถานะทางออกด้านซ้ายเป็นศูนย์


3
คุณจะทราบว่าเปลือกหอยศูนย์รหัสทางออกประเมินที่แท้จริงจึงไม่ใช่ศูนย์รหัสทางออกทางด้านซ้ายของ&&ผลลัพธ์ในการแสดงออกทั้งจะกลับเท็จ ?
ตอบโต้

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

1
@countermode ฉันขอโทษคุณพูดถูกฉันคิดว่าใน Linux zero = false และไม่ใช่ศูนย์ = จริง (เช่นใน C และภาษา / สภาพแวดล้อม / แพลตฟอร์มอื่น ๆ อีกมากมาย) ฉันขอโทษสำหรับความเข้าใจผิด
Try2Help
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.