อะไรคือสิ่งที่เทียบเท่ากับ && เมื่อเขียนสคริปต์ทุบตี


31

ฉันต้องขออภัยล่วงหน้าหากนี่เป็นคำถามที่ซ้ำกัน ฉันพยายามค้นหา / ตรวจสอบก่อนถามที่นี่

ฉันรู้สึกสะดวกสบายกับการเขียนหนึ่ง liners เช่นนี้:

foocommand && foocommand2 && foocommand3

แนวคิดที่ว่าฉันต้องการเพียงคำสั่งที่ตามมาเท่านั้นที่จะทำงานหากคำสั่งก่อนหน้านี้ "สำเร็จ"

ฉันกำลังเขียนสคริปต์ที่ค่อนข้างยาวและหนึ่งบรรทัดนี้เป็นไปไม่ได้เพราะมันดูเหมือนว่าจะทำให้ผู้อื่นสับสนรหัสขนาดใหญ่

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


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

1
พฤติกรรมที่คุณกำลังอธิบายซึ่งมาจาก||และ&&(ตรงกันข้ามกับ|หรือ&) เรียกว่าการลัดวงจร พฤติกรรมที่ใช้กับผู้ประกอบการหลังเรียกว่าการประเมินความกระตือรือร้น
AndyPerfect

7
@kojiro: ฉันไม่เห็นความแตกต่าง a && b && cจะทำงานเฉพาะbถ้าaประสบความสำเร็จดังนั้น "เพียงทำงานcถ้าbประสบความสำเร็จ" และ "เพียงทำงานcถ้าaและbทั้งสองประสบความสำเร็จ" เป็นงบเทียบเท่า: bไม่สามารถประสบความสำเร็จเว้นแต่aประสบความสำเร็จ
ruakh

1
@ruakh a || b && cเป็นตัวอย่างเพิ่มเติม
kojiro

8
@ruakh ไม่ออกจะtrue || false && echo hi ข้อมูลจำเพาะอ่านตัวดำเนินการ "&&" และ "||" จะต้องมีลำดับความสำคัญเท่ากันและจะถูกประเมินด้วยการเชื่อมโยงด้านซ้าย hi
kojiro

คำตอบ:


23

คุณสามารถทำได้เช่นนี้:

#!/bin/sh
ls -lh &&
    # This is a comment
    echo 'Wicked, it works!'

ฉันหวังว่าฉันเข้าใจสิ่งที่คุณถามถูกต้อง


ขอบคุณ นี่เป็นสิ่งที่ใกล้เคียงกับที่ฉันหวังไว้มากที่สุด และทำให้แปลงกลับเป็นซับได้ง่ายมากหากต้องการ
Mike B

ไมค์เนื่องจากคุณกังวลเกี่ยวกับความสะอาดของรหัสการประชุมทั่วไปคือการเยื้องส่วน 2-N ของห่วงโซ่ที่อยู่ใต้ส่วนแรก
jblaine

@jblaine ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณหมายถึง คุณช่วยอธิบายรายละเอียดได้ไหม?
Mike B

Mike, Stackexchange จะไม่ให้ฉันจัดรูปแบบคำตอบของฉันอย่างถูกต้องดังนั้นนี่คือทั้งหมดที่ฉันหมายถึง: เยื้อง
jblaine

@jblaine จุดดีแก้ไขเพื่อเยื้องบรรทัด
Volker Siegel

38

คุณสามารถเปลี่ยนสาย shebang เป็น

#!/bin/bash -e

หลังจากข้อผิดพลาดสคริปต์จะหยุด


1
น่าสนใจ ฉันจะจำไว้ ขอขอบคุณ.
Mike B

ช่วยฉันจากการพิมพ์ set -e เมื่อฉันต้องการมัน
Silverrocker

@Silverrocker มันเป็น POSIX ด้วย (ยกเว้นbashส่วนหนึ่งของหลักสูตร) POSIX setเปลือกใช้เวลาพวงของตัวเลือกที่มีผลบังคับใช้กับ หรือในทางกลับกัน? setเป็นวิธีการตั้งค่าตัวเลือกบรรทัดคำสั่งเชลล์ภายในสคริปต์
Kaz

7
น่าเสียดายที่มีระบบสาธารณูปโภคมาตรฐานจำนวนมากที่ไม่ปฏิบัติตามข้อกำหนดสถานะทางออกปกติดังนั้น-eอาจทำให้การทำงานผิดพลาดได้ ตัวอย่างเช่นคุณอาจไม่ต้องการให้สคริปต์ยุติทุกครั้งที่คุณdiffมีไฟล์ที่ไม่เหมือนกันสองไฟล์ แน่นอนคุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยการต่อท้ายคำสั่ง|| true(หรืออาจจะ|| [ $? = 1 ]) แต่ OP กล่าวถึง "คนอื่น" ที่จะต้องอ่านสคริปต์นี้และพูดว่า "คนอื่น" อาจจะไม่คุ้นเคย -eรับมือกับ
ruakh

4
ผมเคยใส่-eในเธอปังจนกว่าผู้ดูแลระบบของ บริษัท ของฉันเก็บไว้เปิดตัวสคริปต์ของฉันด้วยดังนั้นจึงไม่สนใจbash myscript.sh -eตอนนี้สคริปต์ทั้งหมดของฉันมีset -eบรรทัดที่สอง
Carlos Campderrós

19

หากคุณไม่ชอบset -eความคิดคุณอาจพลิกกลับตรรกะ

foocommand || exit 1
foocommand2 || exit 2
foocommand3 || exit 3

มีประโยชน์มากขึ้นแทนที่exitด้วยบางสิ่งเพื่อพิมพ์ข้อความแสดงข้อผิดพลาดที่มีประโยชน์แล้วออก ภายในฟังก์ชั่นของหลักสูตรที่คุณต้องการแทนreturnexit


11
หรือfoocommand || exitเพื่อออกด้วยfoocommandสถานะออกหากไม่ใช่ศูนย์
Stéphane Chazelas

มันทำงานอย่างไร เป็นเช่นเดียวกับใน C - ถ้าอาร์กิวเมนต์ด้านซ้ายประเมินเป็น TRUE จะไม่มีการตรวจสอบข้อโต้แย้งเพิ่มเติมอีกหรือไม่
Vorac

ใช่ถูกแล้ว. มันเป็นสำนวนสามัญใน Lisp (และภาษาที่ใช้งานได้โดยทั่วไปฉันคิดว่า) และใน Perl
tripleee

9

คุณสามารถใช้if else fiบล็อกแทน

if foocommand; then

  # some comments

  if foocommand2; then

    # more comments

    foocommand3
  fi
fi

มันอ่านง่ายขึ้นอีกนิด

หรือคุณสามารถใช้\เพื่อแบ่งซับขนาดใหญ่ออกเป็นหลายบรรทัด

foocommand && \
  # some comment
  foocommand2 && \
    # more comment
    foocommand3

แต่แน่นอนว่านี่อาจสร้างความสับสนให้แก่ดวงตาที่ไม่ได้รับการฝึกฝน


4
ฉันไม่คิดว่า\มันจำเป็น
ซามูเอลเอ็ดวินวอร์ด

คุณพูดถูก พลังแห่งนิสัย
Martín Canaval

5

คุณสามารถพิจารณาใช้ifคำสั่งที่ซ้อนกัน ตัวเลือกอื่นคือใช้หยิกเป็นกลุ่มเช่น{ true && echo hi; } || echo huh

อัปเดต 1:

นี่คือตัวอย่างที่ไม่มี newlines / comments:

{ { false && echo "inner true"; } && { echo "inner true" && true; } || { echo "inner false" && false; } || echo "outter false"; }

@ สเตฟานขอบคุณที่เพิ่มเซมิโคลอน ฉันใช้โทรศัพท์เพื่อตอบกลับดังนั้นฉันจึงไม่ได้ตรวจสอบคำตอบอีกสองครั้ง :)
livingstaccato

ความคิดที่น่าสนใจ ใช่ฉันเคยคิดที่จะซ้อนกันถ้าคำพูด แต่ถ้าฉันผูกมัดหลายอย่างเข้าด้วยกันมันอาจจะยุ่ง
Mike B

4

แยกแต่ละคำสั่งออกเป็นฟังก์ชัน:

big_block_1() {
  # ...
}
big_block_2() {
  # ...
}
big_block_3() {
  # ...
}

big_block_1 && big_block_2 && big_block_3

0

ฉันมักจะชอบเขียนฟังก์ชั่น "ล้มเหลว" ซึ่งให้ฉันระบุสิ่งที่ฉันจะทำเมื่อเกิดความล้มเหลวแล้วใช้||รูปแบบ ชอบดังต่อไปนี้:

function fail() {
  echo "Failure: ${@}"
  exit 1
}

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