ในทุบตีฉันจะหนีเครื่องหมายอัศเจรีย์ได้อย่างไร


172

ฉันต้องการทำบางสิ่งเช่น bzr commit -m "It works!". ฉันสามารถหลบหนีจากเครื่องหมายอัศเจรีย์ได้โดยทำ bzr commit -m "It works\!". อย่างไรก็ตามข้อความยืนยันของฉันรวมถึงแบ็กสแลช ฉันจะหลีกเลี่ยงเครื่องหมายอัศเจรีย์ในขณะที่ยังคงละเว้นเครื่องหมายแบ็กสแลชได้อย่างไร


1
การทำ bzr commit -m "It works"! ทำงานได้เช่นกัน
kba

1
ดังที่ฉันได้บันทึกไว้ก่อนหน้าคำสั่งที่คุณใส่ใช้งานได้จริงเป็นของตัวเอง :) bzr commit -m "It works!"
h4unt3r

กรณีที่แปลกประหลาดด้วยคำพูดซ้อน: stackoverflow.com/questions/22125658/...
Ciro Santilli 新疆改造中心 六四事件 法轮功

แม้ว่าคำตอบที่ได้รับการยอมรับนั้นเป็นวิธีการแก้ปัญหาที่ดีสำหรับปัญหาความมุ่งมั่นของคุณ แต่ฉันรู้สึกว่ามันไม่ใช่คำตอบสำหรับปัญหาจริง: การขยายประวัติทุบตี . โปรดพิจารณาการยอมรับคำตอบของเดนนิส
Arjan

คำตอบ:


144

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

bzr commit -m 'This does work!' 

23
เนื่องจากคำถามคือ "ฉันจะหลีกเลี่ยงเครื่องหมายอัศเจรีย์ได้อย่างไร" และไม่ใช่ "ฉันจะไม่ขยายเครื่องหมายอัศเจรีย์ได้อย่างไร" ฉันไม่คิดว่ามันถูกต้อง มีบางครั้ง (เช่นเมื่อผ่านเครื่องหมายอะโพสโทรฟีและเครื่องหมายอัศเจรีย์ในบรรทัดคำสั่งเดียวกัน) ว่าสิ่งนี้ไม่ทำงาน คำตอบด้านล่างนี้ทำงานได้ดีกว่ามากในการทำสิ่งที่หลายคนต้องการ
Jann

7
@ Jann: คุณถูก 100% แต่ฉันคิดว่าปัญหาคือที่นี่มีคำถามมากมายเกี่ยวกับ superuser: เราจะตอบคำถามจนถึงจุดหรือเราช่วยคนแก้ปัญหาเฉพาะของพวกเขา ฉันคิดว่าทั้งสองวิธีมีประโยชน์และนี่ก็คือการขอความช่วยเหลือในเรื่องที่เฉพาะเจาะจง
Benjamin Bannier

Touch?! นี่เป็นปัญหาเฉพาะ ฉันมักจะต้องการคำตอบสำหรับคำถามของฉันเพื่อให้สามารถใช้ในสถานการณ์ต่างๆ pS: เหตุผลที่ฉันพูดถึงเรื่องนี้ก็คือฉันต้องผ่านทั้งเครื่องหมายอัญประกาศเดี่ยวและเครื่องหมายอัศเจรีย์ไปยังโปรแกรม perl และฉันต้องการโซลูชันด้านล่าง :)
Jann

ฉันเห็นด้วยกับทั้งเบนจามินและแจน แต่ลงคะแนนให้ ชื่อของคำถามนั้นจัดทำดัชนีโดยเสิร์ชเอ็นจิ้นและนั่นคือวิธีที่ฉันมาที่นี่และผู้ใช้ส่วนใหญ่มาที่นี่ นั่นเป็นเหตุผลที่ฉันเชื่อว่ามันเป็นสิ่งสำคัญที่คำถามจริงสะท้อนให้เห็นถึงปัญหาที่อยู่เบื้องหลัง ในฟอรัมอื่น ๆ ผู้คนจะได้รับคำแนะนำ (บังคับเกือบ) เพื่อถามสิ่งที่พวกเขามองหาอย่างแม่นยำ การตอบคำถามที่แสดงออกมาไม่ดีสนับสนุนความเลอะเทอะและนั่นคือเหตุผลที่แน่นอนสำหรับ downvote ของฉันที่นี่ ข้อเสนอแนะของฉันคือการประนีประนอม / แก้ไขเพื่อช่วยปรับหัวเรื่องเพื่อให้สะท้อนถึงปัญหาที่แท้จริง
ChristophK

146

นี่คือวิธีอื่นถ้าคุณต้องการอัญประกาศเช่นเดียวกับอัศเจรีย์:

echo "It's broken"'!'

มันใช้งานได้แม้ว่า ! ไม่ได้อยู่ที่ท้ายบรรทัด

ตัวอย่างเช่น

echo "hello there"'!'" and goodbye"

โบนัส: สามารถใช้เทคนิคที่คล้ายกันเพื่อหลบหนี ใด ข้อความใน Sh หรือ Bash (ด้วยความช่วยเหลือของ sed): ดูตัวเลือกแรกใน คำตอบนี้ . นอกจากนี้หากคุณมี bash-completion ติดตั้งคุณน่าจะมี quote() ฟังก์ชัน วางจำหน่ายแล้ว


4
คำแนะนำที่ดี JWD ฉันไม่ได้ตระหนักถึงสตริง bash ที่สามารถต่อกันได้โดยการเว้นช่องว่างระหว่างพวกเขา
Alan H.

ที่จริงถ้าเครื่องหมายอัศเจรีย์ท้ายสตริงคุณอยู่ในที่ชัดเจน echo "Happy birthday!" จะทำงานได้ตามที่คาดไว้มิฉะนั้นคุณสามารถหลบหลีกมันด้วยแบ็กสแลช แต่แบ็กสแลชจะถูกพิมพ์เช่นกัน XD Bash ไม่เหมาะสำหรับคนที่ใจหดหู่ :)
h4unt3r

@ h4unt3r: แปลกนี่ไม่ใช่ประสบการณ์ของฉัน สำหรับฉัน, echo "Happy Birthday!" เอาต์พุต 2 บรรทัด ที่แรกก็คือ echo "Happy birthday" (ไม่มีเครื่องหมายอัศเจรีย์) และข้อที่สองคือ "สุขสันต์วันเกิด" (อีกครั้งไม่มีเครื่องหมายอัศเจรีย์) คุณเปิดใช้งานการขยายประวัติเมื่อคุณทำการทดสอบนี้หรือไม่?
jwd

@jwd คุณใช้ bash เวอร์ชันใดอยู่ ฉันมักจะมีการขยาย hist บน คุณใช้สองอย่างโดยไม่ตั้งใจ !! สำหรับการทดสอบของคุณ?
h4unt3r

@ h4unt3r: version 4.1.2(1)-release (x86_64-redhat-linux-gnu)แน่นอนเพียงคนเดียวเท่านั้น ! กำลังใช้. ฉันมี histexpand นำเสนอใน $SHELLOPTS. อย่างไรก็ตามฉันเพิ่งลอง 4.3.18 (2) - ปล่อยบนเครื่องอื่นและมันจะทำงานตามที่คุณอธิบาย ฉันคิดว่ามันเป็นข้อผิดพลาดที่ได้รับการแก้ไข
jwd

64

ปิด การขยายประวัติ :

set +H

หรือ

set +o histexpand

คุณสามารถเพิ่มหนึ่งในคำสั่งเหล่านั้นไปยังของคุณ ~/.bashrc หากคุณมักจะไม่ใช้การขยายประวัติ

Bash 4.3 ได้เพิ่ม กรณีพิเศษ :

อักขระส่วนขยายประวัติจะถูกใช้เป็นเครื่องหมายคำพูดหากนำหน้าเครื่องหมายอัญประกาศคู่ปิดทันทีในสตริงที่มีเครื่องหมายคำพูดคู่


ขอบคุณ - สิ่งนี้ใช้ได้ แต่ฉันต้องทำ set +o histexpandไม่ใช่ set -o histexpand. คุณสามารถแก้ไขคำตอบเพื่อแก้ไขได้ไหม
Matthew

โอ๊ะโอพิมพ์ผิด คงที่
Dennis Williamson

ที่ดีเยี่ยม! กำลังมองหาสิ่งนี้สำหรับอายุ .... หนี vmas ไม่ทำงาน ... ฉันไม่ต้องการใช้คำพูดเดียวเช่นกัน ... ฉันจะเพิ่มสิ่งนี้ในของฉัน .bashrc ขอบคุณ !! ไม่เคยใช้ ! ในสคริปต์และเพื่ออะไร !! มันหนักใจเสมอ ...
Aquarius Power

มันยอดเยี่ยมมาก! echo "@AquariusPower!"
joehanna

10

ใช้เครื่องหมายคำพูดเดี่ยว (') แทนเครื่องหมายคำพูดคู่ (") เครื่องหมายคำพูดเดี่ยวปิดการแปลความหมายทั้งหมดของสิ่งเหล่านั้น

bzr commit -m 'It works!'

4

ตอนนี้ฉันเพิ่งพบวิธีอื่นที่อย่างน้อยจะทำงานด้วย echo ไอเอ็นจีสตริง (ประโยค) คุณต้องการคั่นด้วยเครื่องหมายอัศเจรีย์ มันรันรอบรันด์มากหรือน้อยรอบ ๆ Bash histexpand และใช้เวลาในการโค้ดอีกเล็กน้อย

เลขฐานสิบหกสำหรับเครื่องหมายอัศเจรีย์ตามที่ระบุไว้ใน http://www.ascii-code.com/ คือ 21 ดังนั้นถ้าคุณใส่ \x21 ในตอนท้ายของสายอักขระของคุณ echo -e $fooทำ $foo เสียงก้องที่ขยายออกมาเอง [เช่น foo=$(echo -e "$foo") ] สิ่งที่คุณได้รับเมื่อคุณ echo $foo อีกครั้งเป็นสตริงที่มี ! ในตอนท้าย และไม่มีการสลับระหว่างการขยาย

ทำงานได้อย่างแน่นอนใน Bash 4+ รุ่นก่อนหน้า ymmv


อืมมันไม่ได้ผลสำหรับฉัน
lzap

ฉันไม่ได้สิ่งที่คุณพูดเกี่ยวกับการสะท้อนตัวเอง 'echo -e' และ 'printf' ตีความรหัส escal แปด, ฐานสิบหกและ Unicode หนี ในกรณีที่คุณใช้อย่างใดอย่างหนึ่งคุณสามารถใช้ "\ 041" (ฐานแปดสำหรับ "!") หรือ "\ x21" (ฐานสิบหก) เพื่อยืนในเครื่องหมายอัศเจรีย์ ตัวอย่างเช่น: printf "OMG\041". หากคุณกำลังสร้างสตริงที่มีเครื่องหมายคำพูดคู่อยู่ที่ไหนสักแห่งที่ไม่ใช่ echo หรือ printf เช่นเดียวกับที่คอมมิตสตริง OP ถามเกี่ยวกับคุณสามารถฝัง $(echo -e "\041") ในสตริงที่ควรมีเครื่องหมายอัศเจรีย์ อย่างนี้: bzr commit -m "This is a great commit$(echo -e "\041")".
Todd Walton
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.