ทำไมคำสั่ง“ echo -e” ดูเหมือนจะไม่สร้างเอาต์พุตที่ถูกต้อง?


21

ใน terminal ของ Ubuntu 18.04 LTS เมื่อฉันเขียนคำสั่งนี้:

echo -e "Hello\\\n"

มันให้สิ่งนี้เป็นผลลัพธ์:

Hello\n

แต่ควรพิมพ์ตามที่หน้าคนบอกว่า:

Hello\

นั่นคือพิมพ์ครั้งแรกHelloจาก\นั้นตามด้วยอักขระขึ้นบรรทัดใหม่ (และขึ้นบรรทัดใหม่อีกบรรทัด) ปัญหาอยู่ที่ไหน

ดูecho -eคำสั่งเหล่านี้และผลลัพธ์ของมัน :

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n

ใช่สำหรับ 2 \ แรกมันควรจะส่งออก \ และสุดท้าย \ และ n ทำให้แบ็กสแลชหนี \ n (บรรทัดใหม่) ดังนั้นทำไมจึงควรพิมพ์ Hello \
yolin00

1
ลองโดยไม่ต้องใส่เครื่องหมายคำพูด
ajgringo619

2
คำตอบที่น่าอัศจรรย์นั้นจัดทำโดย Eliah Kagan ซึ่งคุณควรยอมรับ
วานาเดียม

2
อย่าใช้ในครั้งแรกที่ใช้งาน: ใช้echo printf
chepner

2
ใช้อัญประกาศเดี่ยวเสมอหากคุณต้องการแน่ใจว่าสิ่งที่คุณเขียนนั้นแม่นยำสิ่งที่ส่งผ่านไปยังคำสั่งเป็นอาร์กิวเมนต์
Giacomo Alzetta

คำตอบ:


29

แบ็กสแลชได้รับการดูแลเป็นพิเศษโดยecho -eแต่บางครั้งพวกเขาจะได้รับการดูแลเป็นพิเศษโดยเชลล์ (ซึ่งในกรณีนี้คือbash) ตามกฎการอ้างอิงของเชลล์

อาร์กิวเมนต์จริงเห็นคือecho Hello\\nเพราะคุณได้ผ่าน-eไปechoก็ถือว่าทับขวาหนีออกมาเป็นพิเศษและจะทรุดลงไปเป็นหนึ่งเดียว\\ \รอบชิงชนะเลิศnไม่ได้หลบหนีดังนั้นจึงปรากฏขึ้นอย่างแท้จริง

เหตุผลสำหรับเรื่องนี้คือก่อนที่จะแยกจากการทำงานของechoตัวมันเองเชลล์จะให้การดูแล\เป็นพิเศษในบางบริบท unquoted \ตัวละครได้รับการปฏิบัติเสมอพิเศษเดียวที่ยกมา \จะไม่ได้รับการปฏิบัติเป็นพิเศษ แต่การรักษาของยกมาสองครั้ง \ตัวละครในขณะที่คำสั่งที่คุณวิ่งเป็นที่ลึกซึ้งมากขึ้นและมีความซับซ้อน

เมื่อเปลือกพบข้อความยกมาสองครั้งในคำสั่งเช่นเดียวกับ"Hello\\\n"ก็ถือว่า\เป็นตัวหนีเมื่อมันนำหน้าตัวอักษรที่ตัวเองสามารถมีความหมายพิเศษภายในราคาคู่และไม่เป็นอย่างอื่น

  1. เพราะ\บางครั้งมีความหมายพิเศษภายใน""เป็น\ก่อนเกิดอีกมีผลของการอ้างที่สองว่า\ \ดังนั้นภายในราคาคู่แรกจะทรุดลง\\\
  2. หลังจากที่ทั้งสองคนแรกที่\ตัวละครมีความเป็นหนึ่งในสาม\ตัวละครซึ่งเป็นผลกระทบจากสองครั้งแรกและผู้ที่นำไป nแต่nไม่ใช่ตัวละครที่ได้รับการปฏิบัติเป็นพิเศษในเครื่องหมายคำพูดคู่ดังนั้น\ก่อนที่มันจะไม่ได้รับการปฏิบัติเป็นพิเศษในสถานการณ์นี้ ดังนั้นการเข้าพัก\n\n

ผลที่ได้คือว่าในราคาคู่ถูกตีความว่าเป็น\\\n\\n

เมื่อecho -eเห็น\\nสิ่งแรก\จะลบความหมายพิเศษออกจากข้อที่สองดังนั้นจึงechoพิมพ์ออกมาอย่าง\nแท้จริงสำหรับข้อความนั้น


ถ้าเป้าหมายของคุณคือการพิมพ์Helloด้วยการขึ้นบรรทัดใหม่พิเศษ แต่ไม่มีเครื่องหมาย (คำถามเดิมที่ไม่ชัดเจนเกี่ยวกับเรื่องนี้บวกฉันคิดว่ามันเป็นตัวอย่างที่มีประโยชน์) \จากนั้นหนึ่งในการแก้ปัญหาคือการเอา ใช้echo -e "Hello\\n"เอาต์พุตที่Helloมีบรรทัดใหม่พิเศษในตอนท้าย

echo -e 'Hello\n'ทางออกที่ดีคือการใช้คำพูดเดียวและการเขียน เครื่องหมายคำพูดเดี่ยวเป็นรูปแบบที่แข็งแกร่งที่สุดของการอ้างอิง วิธีการแก้ปัญหาที่ดียิ่งขึ้นมักจะใช้printfแทนซึ่งในกรณีนี้จะเป็นechoprintf 'Hello\n\n'

หากเป้าหมายของคุณคือการพิมพ์Hello\รวมถึงแบ็กสแลชแล้วตามด้วยการขึ้นบรรทัดใหม่แล้ววิธีการเสนอราคาแบบ double-quote ก็เป็นไปได้ แต่ก็ยุ่งยาก หากต้องการค้นหาให้ทำงานย้อนหลัง: echo -eแปลง\\เป็น\และ\nขึ้นบรรทัดใหม่และเปลี่ยนเป็นสองเท่า\\เพื่อ\ให้คุณสามารถทำได้ด้วยเครื่องหมายแบ็กสแลชหกตัว ( echo -e "Hello\\\\\\n") เนื่องจาก\\nกลายเป็น\nแบ็กสแลชอันหนึ่งที่หนีอีกอันหนึ่ง คุณสามารถทำได้ด้วยห้าเพราะการโควตแบบสองครั้งจะคงไว้\nเมื่อ\ไม่รอด

สิ่งนี้แสดงให้เห็นถึงประโยชน์ของการอ้างเพียงครั้งเดียว: เพียงใส่สิ่งที่คุณต้องการecho -eเห็นในเครื่องหมายคำพูดเดี่ยว ( echo -e 'Hello\\\n') printfก็ดีที่นี่ printf 'Hello\\\n\n'ทางเลือกหนึ่งคือ แต่ที่printfส่องสว่างจริงๆคือคุณสามารถเสียบอาร์กิวเมนต์เพิ่มเติม คุณสามารถใช้printf '%s\n\n' 'Hello\'ซึ่งแทรกอาร์กิวเมนต์ที่สอง (ตัวอักษรHello\เพราะราคาเดียวไม่ได้เปลี่ยนอะไร) %sในสถานที่ของ

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