มีความแตกต่างระหว่าง '&&' กับ ';' หรือไม่ สัญลักษณ์ในเทอร์มินัล BASH มาตรฐานหรือไม่


56

พวกเขาดูเหมือนจะส่งสัญญาณทั้งสองเพื่อทุบตีเพื่อเริ่มต้นด้วยคำสั่งอื่นตามสัญลักษณ์ แต่มีความแตกต่างอย่างชัดเจนหรือไม่?

คำตอบ:


75

ด้วยสายนี้:

command1 && command2

command2 จะถูกดำเนินการหาก (และเฉพาะในกรณีที่) command1 ส่งคืนสถานะทางออกเป็นศูนย์ในขณะที่อยู่ในบรรทัดนี้:

command1 ; command2

ทั้ง command1 และ command2 จะถูกดำเนินการโดยไม่คำนึงถึง อัฒภาคอนุญาตให้คุณพิมพ์คำสั่งมากมายในหนึ่งบรรทัด


1
ที่น่าสนใจ! ฉันคิดว่ามันอาจจะเป็นวิธีที่สะดวกสบายกว่า ขอขอบคุณ!

42

คุณสามารถลองใช้ความแตกต่างด้วยตัวคุณเอง:

  1. ls /invalid/path && echo "hello!"
    เนื่องจาก / ไม่ถูกต้อง / เส้นทางไม่มีอยู่ ls ไม่สามารถแสดงรายชื่อไดเรกทอรีให้คุณ มันจะล้มเหลวพร้อมกับข้อความแสดงข้อผิดพลาด: "ls: / invalid / path: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" ครึ่งหลังของคำสั่ง (echo "Hello!") คือไม่เคยดำเนินการแม้เพราะครึ่งปีแรกล้มเหลว

  2. ls /invalid/path ; echo "hello!"
    ข้อความแสดงข้อผิดพลาดเหมือนเดิมปรากฏขึ้น แต่คราวนี้ส่วนที่สองจะถูกดำเนินการ !
    ls: / ไม่ถูกต้อง / พา ธ : ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
    สวัสดี!

ทำไมถึงมีประโยชน์
สมมติว่าคุณต้องการแตกไฟล์ชื่อ archive.tar.gz
คุณสามารถใช้คำสั่งtar zxvf archive.tar.gz && rm archive.tar.gzได้
หากการดึงข้อมูลที่เก็บถาวรล้มเหลวไม่ว่าด้วยเหตุผลใดส่วนที่สองจะไม่ถูกดำเนินการ! คุณสามารถลองอีกครั้ง

ถ้าคุณใช้; ในสถานการณ์เดียวกันการเก็บถาวรจะถูกลบและคุณไม่สามารถลองอีกครั้งได้


8

&&คือANDหมายความว่าคำสั่งที่สองจะดำเนินการหากคำสั่งแรกส่งคืนจริง (ไม่มีข้อผิดพลาด)


1
&& คือ "แล้ว" (ไม่ใช่ "และ") ... ดูคำตอบของฉัน
Peter.O

2
@ เฟรดฉันจะบอกว่ามันเป็น"และ" ที่มีการประเมินการลัดวงจร - ถ้าส่วนแรกไม่เป็นความจริงก็รู้ว่าผลลัพธ์ทั้งหมดต้องเป็นเท็จดังนั้นจึงข้ามส่วนที่สอง แต่ยอมรับว่าการคิดว่ามันเป็น "แล้ว" ไม่ค่อยสร้างความแตกต่างมากในบริบทนี้
jg-faustus

2
@ เฟร็ดแม้ว่าแนวคิดอาจจะเข้าใจง่ายกว่า แต่ฉันไม่เห็นด้วยกับข้อความของคุณ แนวคิดก็คือว่าด้วยการดำเนินการใด ๆ ANDพารามิเตอร์ที่ 2 จะไม่เกี่ยวข้องหากหนึ่งแรกเท่ากับfalseและดังนั้นรหัสพื้นฐานได้รับการปรับให้เหมาะสมเพื่อเลื่อนการประเมินของพารามิเตอร์ที่ 2 จนกว่ามันจะรู้ว่าสิ่งแรกคือ
Ward Muylaert

2
@ เฟรดฉันไม่แน่ใจว่าตัวอย่างนั้นพยายามทำอะไร &&เป็นเพียงตัวดำเนินการไบนารีฟังก์ชัน สิ่งที่ "พิเศษ" เท่านั้นคือมันเป็นสัญกรณ์มัด (ซึ่งเป็นมาตรฐานสำหรับส่วนใหญ่ของผู้ประกอบการประเภทนี้ต่อไป) และการดำเนินการล่าช้าของตัวถูกดำเนินการที่สอง การดำเนินการล่าช้านั้นทำให้สามารถใช้เป็นสิ่งที่สามารถมองเห็นแนวคิดในฐานะifคำสั่งในบริบทนี้แต่ไม่ได้นำออกไปจากความจริงที่ว่าการใช้งานที่ตั้งใจไว้เดิมนั้นอยู่ภายใต้เงื่อนไขของifคำสั่งจริง การใช้ที่นี่จริงๆเป็น "แฮ็ค" มากกว่า
Ward Muylaert

3
@fred แน่นอนมันไม่ได้เป็นผู้ประกอบการ ternary a && b || c = (a && b) || cมันก็คือการสืบทอดของทั้งสองการดำเนินงาน ลำดับของการประเมินผลง่าย ๆ ที่นั่นไม่มีเรื่องลึกลับเลย or(and(a, b), c)ถ้าคุณจะเขียนพวกเขาเช่นฟังก์ชั่นปกติของคุณมันก็จะมีลักษณะ ตรรกะนี้เหมือนกันภายในifเงื่อนไขเช่นเดียวกับเมื่อป้อนมันโดยตรงในบรรทัดคำสั่งเพราะ&&และ||เป็นตัวดำเนินการพวกมันจะถูกดำเนินการสองตัวและพวกมันจะคืนค่าอีก
Ward Muylaert

8

อัปเดต : ฉันได้เพิ่มเป็นสคริปต์เพื่อดักจับกับดักที่เป็นไปได้บางส่วน:

เพราะไม่มีใครพูดถึง "||" ฉันจะ

อัปเดต 2 : การใช้ถ้อยคำที่สำคัญอีกครั้งที่นี่
&& เหมือนกับคำว่า "จากนั้น" ของคำสั่ง "ถ้า" ซึ่งตอบสนองต่อ "จริง"

|| จะไม่ชอบ "อื่น" ของ "ถ้า" งบ ..
|| เป็นเหมือนคำสั่ง "แล้ว" ของคำสั่ง "ถ้า" ซึ่งตอบสนองต่อ "เท็จ"

specificaly เพิ่มเติม && ทดสอบ $? ส่งคืนค่าของคำสั่งที่ถูกเรียกใช้ล่าสุดก่อนหน้า นี้และผ่านการควบคุมไปยังคำสั่งหรือ sub-shell ทันทีหลังจาก && ... มันจะผ่านการควบคุมถ้า $ เท่านั้น? เป็นความจริง.

|| คล้ายกันและมักจะเห็นตามคำสั่ง && แต่จะทดสอบค่าส่งคืนที่ผิดพลาด ($?) จากคำสั่งที่ดำเนินการล่าสุดก่อนหน้า นี้ ... NB! , Nota Bene! โปรดทราบ! .... หากคำสั่ง predecing เป็นคำสั่ง && ซึ่งมีการเรียกคืนเป็นเท็จเมื่อคุณคาดหวังว่าคำสั่งนั้นเป็นจริงดังนั้น || จะตอบกลับไปเป็นเท็จดังนั้นการผสมทั้งสองในบรรทัดเดียวกันอาจมีความเสี่ยง

ประเด็นหลักที่ฉันพยายามทำคือเกี่ยวข้องกับความผิดพลาดที่ฉันทำ เช่น:
## [[เงื่อนไข]] && A || B
จะได้ไม่ประพฤติเช่น C / C ++ ternary สไตล์ เช่น:
// (เงื่อนไข)? A: B
ดูสคริปต์ด้านล่างเพื่อดูตัวอย่างผลลัพธ์ "ไม่คาดคิด" จาก "A"

การทดสอบพื้นฐานและ && และ | | คำสั่งทั้งหมดจะต้องอยู่ในบรรทัดเดียวกัน ...


เรียกใช้สคริปต์นี้เพื่อดูว่ามีสิ่งใดที่ผิดพลาดเมื่อใช้ && และ || ส่วนใหญ่ดำเนินการเมื่อเร็ว ๆ นี้คำสั่งอาจจะไม่เป็นอย่างใดอย่างหนึ่งที่คุณคาดหวัง ..

[[เงื่อนไข]] && echo Hello || echo Goodbye .... โดยทั่วไปแล้วจะปลอดภัยเนื่องจาก
echo ที่มีรูปแบบถูกต้องจะกลับมาเป็นจริง
แต่สิ่งที่เกี่ยวกับการเข้าถึงไฟล์ที่ไม่ออก?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 



0

คำสั่ง (ฟังก์ชั่นในกรณีของสคริปต์) หลังจาก&&ถูกดำเนินการขึ้นอยู่กับ RETVAL ของคำสั่งแรก (ฟังก์ชั่นในกรณีของสคริปต์) มันบังคับให้คำสั่งแรกคืนค่า 0 ถ้าสำเร็จ เราสามารถตรวจสอบค่าที่ส่งคืนเพื่อดำเนินการคำสั่งเพิ่มเติม

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