ฉันจะแบ่งคำสั่งเชลล์ไปยังหลายบรรทัดได้อย่างไรเมื่อใช้คำสั่ง IF


384

ฉันจะแบ่งคำสั่งผ่านหลายบรรทัดในเชลล์ได้อย่างไรเมื่อคำสั่งเป็นส่วนหนึ่งของifคำสั่ง

งานนี้:

if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1                                                                       
fi

สิ่งนี้ใช้ไม่ได้:

# does not work:
if ! fab --fabfile=.deploy/fabfile.py \ 
  --forward-agent \
  --disable-known-hosts deploy:$target; then   
  rc=1
fi

แทนที่จะได้รับคำสั่งทั้งหมดฉันได้รับ:

./script.sh: line 73: --forward-agent: command not found

สิ่งที่ขาดหายไปจากความเข้าใจใน Bash ของฉันที่จะช่วยให้ฉันเข้าใจเรื่องนี้และปัญหาที่คล้ายกันในอนาคต


2
ข้อผิดพลาดคืออะไร? ฉันสามารถดำเนินการได้$ if ! cp -n log/server1.log \ > .; then echo no copy; fiโดยไม่มีข้อผิดพลาดโดยขึ้นบรรทัดใหม่หลังจาก\
Miserable Variable

15
คุณมีช่องว่างหลังจากแบ็กสแลชเทอร์มินัล\ หรือไม่? พวกเขาดูยากมาก ถ้าคุณทำคุณอาจต้องการดูว่าคุณสามารถทำให้ตัวแก้ไขลบช่องว่างต่อท้ายหรือทำให้มองเห็นได้ชัดเจนขึ้น
msw

10
ใช่มันเป็นช่องว่างหลังจากแบ็กสแลชเทอร์มินัล โดยสิ้นเชิง ขอบคุณ.
Dmitry Minkovsky

และใช่ฉันควรโพสต์ "ข้อผิดพลาด" (ผลลัพธ์ที่ไม่คาดคิด)! ความผิดฉันเอง! กำลังแก้ไขในขณะนี้
Dmitry Minkovsky

คุณเข้าใจอะไร มันไม่ได้เป็นส่วนหนึ่งของคำถาม
hakre

คำตอบ:


566

การต่อเนื่องของบรรทัดจะล้มเหลวหากคุณมีช่องว่าง (อักขระเว้นวรรคหรือแท็บ) หลังเครื่องหมายทับขวาและก่อนขึ้นบรรทัดใหม่ ไม่มีช่องว่างดังกล่าวตัวอย่างของคุณทำงานได้ดีสำหรับฉัน:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
   --forward-agent \
   --disable-known-hosts deploy:$target; then
     echo failed
else
     echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

รายละเอียดบางอย่างได้รับการส่งเสริมจากความคิดเห็น: แบ็กสแลชต่อเนื่องของบรรทัดในเชลล์ไม่ใช่กรณีพิเศษจริงๆ มันเป็นเพียงตัวอย่างของกฎทั่วไปที่แบ็กสแลช "อัญประกาศ" อักขระต่อไปนี้ทันทีป้องกันการรักษาพิเศษใด ๆ ที่โดยปกติจะต้องอยู่ภายใต้ ในกรณีนี้อักขระตัวถัดไปคือบรรทัดใหม่และการดูแลพิเศษที่ถูกป้องกันกำลังยกเลิกคำสั่ง โดยปกติแล้วอักขระที่ยกมาจะรวมอยู่ในคำสั่ง ขึ้นบรรทัดใหม่แบ็กสแลชจะถูกลบทั้งหมด แต่อย่างอื่นกลไกก็เหมือนกัน และเครื่องหมายแบ็กสแลชจะใส่อักขระที่ตามมาทันทีเท่านั้น หากตัวละครนั้นเป็นช่องว่างหรือแท็บคุณเพิ่งได้รับช่องว่างหรือแท็บที่ยกมาและขึ้นบรรทัดใหม่ใด ๆ ที่ตามมายังคงไม่มีการอ้างอิง


5
มาร์คคุณรู้ไหมฉันต้องมีช่องว่าง ฉันสามารถที่จะทำซ้ำข้อผิดพลาดเท่านั้นเมื่อมีการเพิ่มช่องว่างหลังจาก`ฉันได้รับ`s. For example, when adding one after the first ./soundops: line 73: --forward-agent: command not foundปัญหาของฉันคือฉันไม่เข้าใจข้อผิดพลาดนี้ เหตุใดการมีช่องว่างส่งผลให้เกิดข้อผิดพลาดนั้น ช่องว่าง + \n"negates" `` และคั่นคำสั่งหรือไม่
Dmitry Minkovsky

83
แบ็กสแลชที่อยู่ด้านหน้าของบรรทัดใหม่จะป้องกันการขึ้นบรรทัดใหม่จากการยกเลิกคำสั่ง แต่เช่นเดียวกับ escape sequences พิเศษเช่น "\ n" จะทำงานเฉพาะกับ backslash และ n เท่านั้น, backslash-newline จะใช้ได้เฉพาะกับ backslash และ newline เท่านั้น
Mark Reed

18
ฮ่าฮ่าฮ่าว้าวแน่นอนว่าเหมาะสม ไม่เคยเห็นอย่างนั้น เปิดหูเปิดตา แต่เรียบง่ายมาก: มันเป็นเพียงขึ้นบรรทัดใหม่ ฉันเกลียดตัวละครที่มองไม่เห็น พวกเขาจะทำให้ฉันมีเหตุผลมากขึ้นถ้าพวกเขามองเห็นได้ทั้งหมด ขอบคุณ!
Dmitry Minkovsky

7
ในบรรณาธิการส่วนใหญ่คุณสามารถทำให้มองเห็นตัวละครที่มองไม่เห็นเหล่านั้นได้
lucasvc

1
แบ็กสแลชและขึ้นบรรทัดใหม่จะถูกลบออกจากบรรทัดคำสั่งที่มีประสิทธิภาพ แต่ช่องว่างนำหน้าในบรรทัดถัดไปจะถูกรักษาไว้ ดังนั้นไม่ว่าจะเป็นปัญหาหรือไม่ขึ้นอยู่กับว่าช่องว่างจะเป็นปัญหา ณ จุดนั้นในคำสั่งบรรทัดเดียว
Mark Reed

52

สำหรับผู้ใช้ Windows / WSL / Cygwin:

ตรวจสอบให้แน่ใจว่าการสิ้นสุดบรรทัดของคุณเป็นฟีด Unix มาตรฐานเช่น\n(LF) เท่านั้น

การใช้การสิ้นสุดบรรทัดบรรทัด Windows \r\n(CRLF) การสิ้นสุดบรรทัดจะแบ่งตัวแบ่งบรรทัดคำสั่ง


นี้เป็นเพราะมี\ที่ท้ายบรรทัดกับ Windows \ \r \nบรรทัดสิ้นสุดแปลไป
ดังที่มาร์คอธิบายไว้อย่างถูกต้องด้านบน:

การต่อเนื่องของบรรทัดจะล้มเหลวหากคุณมีช่องว่างหลังแบ็กสแลชและก่อนขึ้นบรรทัดใหม่

ซึ่งรวมถึงพื้นที่ไม่เพียง ( ) หรือแท็บ ( \t) แต่รวมถึงการคืนค่าขนส่ง ( \r)


1
วิธีนี้ช่วยแก้ไขปัญหาที่สร้างขึ้นเมื่อสร้างสคริปต์ใน Windows และใช้งานใน Windows bash (เช่น bash -c MyShellScript.sh โดยที่ MyShellScript.sh ถูกสร้างขึ้นในตัวแก้ไข Windows) คุณต้องบันทึก MyShellScript.sh ในรูปแบบ UNIX โดยอาจใช้ notepad ++
BSalita
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.