ทำไม `echo -e“ \\\ SOME_TEXT”` แสดงเครื่องหมายแบ็กสแลชเพียงอันเดียว?


19

บางคนสามารถอธิบายสิ่งที่เกิดขึ้นเบื้องหลังในการหลบหนีของตัวละครในเปลือก Linux? ฉันลองทำสิ่งต่อไปนี้และใช้ Google เป็นจำนวนมากโดยไม่ประสบความสำเร็จในการทำความเข้าใจว่าเกิดอะไรขึ้น (และอย่างไร):

root@sv01:~# echo -e "\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\\ Hello!"
\\\ Hello!
root@sv01:~# echo -e "\n Hello!"

 Hello!
root@sv01:~# echo -e "\\n Hello!"

 Hello!
root@sv01:~# echo -e "\\\n Hello!"
\n Hello!

ฉันหลงทางอยู่ที่นั่นเช่นเหตุใดเครื่องหมายแบ็กสแลชสามรายการจึงให้แบ็กสแลชเดียว ฉันคาดหวังว่า: สองคนแรกจะถูกหลบหนีไปหนึ่งอันที่สามจะไม่พบสิ่งใดที่จะหลบหนีดังนั้นมันจะยังคงเป็นเครื่องหมายทับ (บรรทัดในการทดสอบครั้งแรก) แต่สิ่งที่เกิดขึ้นคือสิ่งที่สามกำลังจะหายไป
ทำไมฉันได้รับหนึ่งทับขวาจากสี่\\\\ Hello? ฉันคาดว่าแต่ละคู่จะให้แบ็กสแลชหนึ่งอัน -> แบ็กสแลชสองตัว

และทำไมฉันต้องมีแบ็กสแลชสามครั้งในกรณีที่ผ่านมาเพื่อ \ n หลบหนี เกิดอะไรขึ้นในพื้นหลังของการหลบหนีเพื่อรับสิ่งนั้น และมันแตกต่างจาก\\nกรณีอย่างไร

ฉันขอขอบคุณคำอธิบายใด ๆ ของสิ่งที่เกิดขึ้นในบรรทัดก่อนหน้า


echo -eพฤติกรรมที่ไม่ได้มาตรฐานที่กำหนดไว้ แต่อย่างใด - ดูpubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html การส่งออกจะสมบูรณ์การดำเนินงานที่กำหนดไว้ว่ามีที่ใดก็ได้ทับขวาตัวอักษรในปัจจัยการผลิตและตัวเลือกที่ได้รับอนุญาตเท่านั้น-n(หมายถึงว่าการดำเนินงานตามมาตรฐานจะมีecho -eการพิมพ์-eในการส่งออกของมัน)
Charles Duffy

... แม้ว่าคุณจะแน่ใจ 100% ว่าเชลล์ของคุณทุบตี แต่ก็ echo -eไม่ปลอดภัย: echoจะทำงานตามมาตรฐานหากเปิดใช้งานทั้งตัวเลือกposixและxpg_echoตัวเลือกรันไทม์หรือหากคอมไพล์ด้วยตัวเลือกการสร้างเวลาที่เทียบเท่ากัน การปฏิบัติที่ปลอดภัยคือการใช้printfแทน - ดูการใช้โปรแกรมประยุกต์และเหตุผลส่วนของการเชื่อมโยงดังกล่าวข้างต้นอธิบายถึงวิธีการที่จะทำให้การทำหน้าที่แทนสำหรับprintf echo
Charles Duffy

คำตอบ:


28

นี่เป็นเพราะbashและecho -eรวมกัน จากman 1 bash

เครื่องหมายแบ็กสแลชที่ไม่ใช่เครื่องหมายอัญประกาศ ( \) เป็นอักขระยกเว้น <newline>จะรักษามูลค่าที่แท้จริงของตัวอักษรถัดไปที่ตามมาด้วยข้อยกเว้นของ [ ... ]

ล้อมรอบตัวอักษรในคำพูดคู่เก็บรักษามูลค่าที่แท้จริงของตัวละครทุกตัวที่อยู่ในคำพูดที่มีข้อยกเว้นของ$`, \[ ... ] เครื่องหมายยังคงมีความหมายพิเศษเฉพาะเมื่อตามด้วยหนึ่งในตัวละครต่อไปนี้: $`, ", หรือ\<newline>

ประเด็นคือ: แบ็กสแลชที่ยกมาเป็นสองเท่านั้นไม่ได้พิเศษเสมอไป

มีการใช้งานต่างๆของอยู่echoโดยทั่วไปก็เป็น builtin ในbash; สิ่งสำคัญที่นี่คือพฤติกรรมนี้:

หาก-eมีผลบังคับใช้ลำดับต่อไปนี้จะถูกจดจำ:
\\
backslash
[…]
\n
บรรทัดใหม่

ตอนนี้เราสามารถถอดรหัส:

  1. echo -e "\ Hello!"- ไม่มีอะไรพิเศษที่จะbashไม่มีอะไรพิเศษที่จะecho; \การเข้าพัก
  2. echo -e "\\ Hello!"- คนแรก\บอกว่าbashจะรักษาที่สองอย่าง\แท้จริง echoได้รับ\ Hello!และทำหน้าที่ดังกล่าวข้างต้น
  3. echo -e "\\\ Hello!"- คนแรก\บอกว่าbashจะรักษาที่สองอย่าง\แท้จริง echoได้รับ\\ Hello!และ (เพราะ-e) ก็ตระหนักถึงความเป็น\\\
  4. echo -e "\\\\ Hello!"- คนแรก\บอกว่าbashจะรักษาที่สองอย่าง\แท้จริง ที่สามพูดเหมือนกันเกี่ยวกับที่สี่; echoได้รับ\\ Hello!และ (เพราะ-e) ก็ตระหนักถึงความเป็น\\\
  5. echo -e "\\\\\ Hello!"- คนแรก\บอกว่าbashจะรักษาที่สองอย่าง\แท้จริง ที่สามพูดเหมือนกันเกี่ยวกับที่สี่; คนสุดท้ายไม่ใช่คนพิเศษ echoได้รับ\\\ Hello!และ (เพราะจาก-e) มันรับรู้เริ่มต้น\\เป็น\สุดท้าย\ยังคงเหมือนเดิม

และอื่น ๆ อย่างที่คุณเห็นแบ็กสแลชต่อเนื่องสูงสุดสี่อันให้ผลลัพธ์ นั่นเป็นเหตุผลที่คุณต้องการ (อย่างน้อย) เก้าคนเพื่อให้ได้สามคน 9 = 4 + 4 + 1

ขณะนี้มี\n:

  1. echo -e "\n Hello!"- ไม่มีสิ่งใดเป็นพิเศษbashecho ได้รับสตริงเดียวกันและ (เพราะ-e) แปล\nเป็นบรรทัดใหม่
  2. echo -e "\\n Hello!"- bashตีความ\\ว่าเป็น\; echoได้รับ\n Hello!และผลลัพธ์จะเหมือนกับด้านบน
  3. echo -e "\\\n Hello!"- bashตีความเริ่มต้น\\เป็น\; echoได้รับ\\n Hello!และ (เพราะจาก-e) มันตีความ\\ว่าเป็นตัวอักษร\ที่จำเป็นต้องพิมพ์

ผลลัพธ์จะแตกต่างกันด้วย'แทนที่จะเป็น"(เนื่องจากbashพฤติกรรมที่แตกต่าง) หรือไม่มี-e( echoพฤติกรรมที่แตกต่าง)


1
ขอบคุณมาก! ดังนั้นมีสองขั้นตอนคือการหลบหนีขั้นตอนที่ทำโดยการทุบตีและขั้นตอนที่สองโดยการ-eตัดสินข้อความที่ตัดสินโดยการทุบตีแล้วใช่ไหม? หากถูกต้องนั่นจะเป็นการขจัดความสับสน คุณอาจจะเอ่ยถึงการsedทำงานของมันได้อย่างไร? มันมีเทคนิคในการหลบหนีของตัวเองหรือไม่? ดังนั้นฉันหมายความว่ามันทำตัวเหมือนเสียงสะท้อนกับ-e?
Mohammed Noureldin

2
@MohammedNoureldin ใช่มีสองขั้นตอน คำถามเดิมของคุณจะปรับมันเป็นให้ไม่ทำให้มัน overcomplicated sedกับ คุณอาจถามคำถามอื่น (ประมาณsedเท่านั้น) เพียงทำวิจัยของคุณเองก่อน
Kamil Maciorowski

3
@MohammedNoureldin sedจะปฏิบัติตามหลักการพื้นฐานเดียวกัน: ทุบตีจะตีความบรรทัดคำสั่งตามกฎการแยกวิเคราะห์ (และอาจจะลบ) คำพูดและการหลบหนี ผลจากการที่ได้รับการส่งผ่านไปsedซึ่งตีความตามของกฎการหลบหนี BTW คุณสามารถทำให้สิ่งนี้ง่ายขึ้นโดยใช้สตริงbashที่มีเครื่องหมายคำพูดเดี่ยวในเนื่องจากไม่ได้แปล eny escape (โดย bash) - bash ลบเครื่องหมายคำพูดเดี่ยวและส่งสิ่งที่อยู่ภายในพวกมันไปยังคำสั่งโดยตรง
Gordon Davisson

ฉันยังมีปัญหาเล็กน้อยในecho -e "\\\n Hello!"กรณี ที่นี่จะทำทุบตีหนีออกมาและมันจะกลายเป็น\\nแล้ว-eจะหลบหนีผล backslashes สองและแล้วพวกเขาก็จะกลายเป็น\\n \nตอนนี้ใครเป็นผู้ตีความ\nเพื่อที่จะขึ้นบรรทัดใหม่? โดยปกติในกรณีของecho -e "\n Hello!"ทุบตีไม่ทำอะไรเลยและ-eตีความ\nเป็นบรรทัดใหม่ แต่ในขั้นตอนการตีความสถานการณ์ที่กล่าวถึงครั้งแรกได้กระทำก่อนที่\nจะได้รับการตีความ คุณช่วยอธิบายได้มั้ย
Mohammed Noureldin

1
ตกลงความผิดของฉันฉันได้อ่านเกี่ยวกับเรื่องนี้เป็นเวลา 2 วันกับคืนของพวกเขาดังนั้นดูเหมือนว่าฉันเริ่มผสมคดีฉันเชื่อว่าฉันมีสิ่งอื่นsedที่ทำให้ฉันสับสนเมื่อคืนนี้ (บางทีฉันอาจทำอะไรผิดเมื่อวานนี้) แต่ตอนนี้ฉัน ลองอีกครั้งเหมือนกันกับecho -eและsedและฉันได้สิ่งเดียวกันยกเว้นขอขอบคุณ!
Mohammed Noureldin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.