“ -bash:!”: ไม่พบเหตุการณ์ "


114

ลองดำเนินการดังต่อไปนี้ภายใต้ bash shell echo "Reboot your instance!"

ในการติดตั้งของฉัน:

root@domU-12-31-39-04-11-83:/usr/local/bin# bash --version
GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@domU-12-31-39-04-11-83:/usr/local/bin# uname -a
Linux domU-12-31-39-04-11-83 2.6.35-22-virtual #35-Ubuntu SMP Sat Oct 16 23:57:40 UTC 2010 i686 GNU/Linux
root@domU-12-31-39-04-11-83:/usr/local/bin# echo "Reboot your instance!"
-bash: !": event not found

ใครช่วยอธิบายหน่อยได้ไหมว่า "เหตุการณ์ทุบตี" ฉันไม่เคยได้ยินแนวคิดนี้มาก่อน นอกจากนี้ฉันควรส่งออก "!" อย่างไร ในตอนท้ายของประโยค?

คำตอบ:


53

set +Hคุณสามารถปิดการเปลี่ยนตัวประวัติศาสตร์โดยใช้


2
คุณรู้เหตุผลที่อยู่เบื้องหลังไวยากรณ์หรือไม่ ดูเหมือนว่าจะตอบโต้สัญชาตญาณจริงๆ คุณคิดว่าคุณพิมพ์+Hเพื่อเปิดใช้งานบางอย่างและ-Hปิดการใช้งานบางอย่าง
Gavin Ward

7
@PunkyGuy: ฉันไม่ทราบประวัติ (ปุนตั้งใจ) ด้านหลัง แต่ตัวเลือก Unix มักจะเริ่มต้นด้วยเครื่องหมายยัติภังค์ (หรือลบ) และ+เป็นตรงกันข้ามกับที่
Dennis Williamson

105

!เป็นอักขระพิเศษในการทุบตีมันถูกใช้เพื่ออ้างถึงคำสั่งก่อนหน้า; เช่น,

!rm

จะเรียกคืนและดำเนินการคำสั่งสุดท้ายที่เริ่มต้นด้วยสตริง "rm" และ

!rm:p

จะเรียกคืน แต่ไม่ดำเนินการคำสั่งสุดท้ายที่เริ่มต้นด้วยสตริง "rm" bash กำลังตีความเครื่องหมายอัศเจรีย์ในecho "reboot your instance!"ฐานะ " แทนที่คำสั่งสุดท้ายที่เริ่มต้นด้วยอักขระ (s) ต่อจากเครื่องหมายอัศเจรีย์ทันที " และบ่นกับคุณว่าไม่สามารถหาเหตุการณ์ (คำสั่ง) ในประวัติของคุณที่เริ่มต้นด้วยคำเดียว อ้างดับเบิล

ลอง

echo reboot your instance\!

เพื่อป้องกัน (ยกเว้น) เครื่องหมายอัศเจรีย์จากการทุบตี


ใช่ แต่ควรเกิดขึ้นถ้าฉันต้องการใช้ echo -e "ข้อความบางส่วน $ ENV_VAL อีกข้อความ \ n เริ่มต้นทันที!" ?
Maxim Veksler

1
เขียนสองคำสั่ง echo; คุณได้รับ linefeed ฟรี
MadHatter

1
วิธีแก้ปัญหาง่ายๆคือใช้เครื่องหมายคำพูดเดี่ยวและเครื่องหมายคำพูดคู่พร้อมกัน: echo -e "Text \ nReeboot" '!'
mmey

4
อันนี้ครับ ถ้าฉันไม่หนีเครื่องหมายอัศเจรีย์ทุบตีจะพอดี ถ้าฉันทำหนีมันทับขวาจะรวมอยู่ในสตริงสุดท้าย ทำไมคุณทำเช่นนี้ทุบตี !! ( pastebin.com/g4PYv56A )
Hubro

2
@Hubro ในความยุติธรรมฉันไม่แน่ใจว่าเป็นความผิดของทุบตี คุณมีเรื่องที่ค่อนข้างซับซ้อนโดยใช้ ruby ​​เพื่อป้อนสิ่งที่จะทุบตีและมันไม่ชัดเจนสำหรับฉันว่า ruby ​​ส่วนใดที่เล่นในการลอกหรือตอกย้ำตัวละครในการหลบหนี
MadHatter

25

หากต้องการแก้ปัญหาต้นฉบับของคุณลองใช้เครื่องหมายคำพูดเดี่ยวแทนที่จะเป็นเครื่องหมายคำพูดคู่ ด้วยตัวหลัง, bash จะพยายามขยายตัวอักขระบางตัวก่อนส่งผลลัพธ์ไปยังคำสั่ง (echo ในกรณีนี้) ด้วยเครื่องหมายอัญประกาศเดี่ยว bash ส่งผ่านสายอักขระทั้งหมดไม่เปลี่ยนแปลง

!ถูกใช้ในคำสั่งเพื่ออ้างถึงประวัติบรรทัดคำสั่ง ดู: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDSสำหรับชุดเต็ม จากตัวอย่างข้างต้นทุบตีพยายามที่จะขยาย!"การอ้างอิงถึงเหตุการณ์ก่อนที่เสียงสะท้อนได้รับการมองในดังนั้นข้อผิดพลาด

โปรดสังเกตว่าในสคริปต์ทั้งหมดของคำสั่งประวัติศาสตร์ถูกปิดใช้งานในขณะที่พวกเขาเท่านั้นที่ให้ความรู้สึกในเปลือกโต้ตอบ

!$เพียงคนเดียวที่ผมใช้เป็นประจำคือ มันจะขยายไปยังอาร์กิวเมนต์สุดท้ายของคำสั่งก่อนหน้า มันเป็นชวเลขที่มีประโยชน์ในสถานที่ต่างๆ


4
!!การกรอกคำสั่งสุดท้ายที่ป้อนเสร็จสมบูรณ์นั้นมีประโยชน์อย่างน่าทึ่ง โดยเฉพาะอย่างยิ่งsudo !!หรือpfexec !!
jgoldschrafe

2
ฉันยังพบว่า sudo และ pfexec เป็นสาธารณูปโภคที่ดี แต่ไม่จำเป็นต้องกระตือรือร้น
LeartS

$_ทำงานในเชลล์มากกว่าทุบตีและเป็นตัวแปรที่เหมาะสมไม่เหมือน!$กัน (และ @LeartS: ฉันชอบอิโมติคอนที่คุณขาดไป);))
ΤΖΩΤΖΙΟΥ

7

เพียงแค่ใส่ช่องว่างระหว่าง! และ "เกินกว่าที่มันจะใช้ได้

ไชโย


2
คุณช่วยเพิ่มคำอธิบายเกี่ยวกับสาเหตุที่โซลูชันของคุณใช้งานได้หรือไม่
200_success

2
ใช้งานได้เพราะ Bash ปฏิบัติต่อ! เป็นอักขระพิเศษหากตามด้วยอักขระที่ไม่ใช่ช่องว่างโดยตรง อย่างไรก็ตามมันจะเพิ่มช่องว่างพิเศษให้กับเอาต์พุตของคุณเพื่อที่อาจไม่ต้องการเสมอไป ...
mmey

2

ใช่! เป็นอักขระพิเศษในการทุบตีมันถูกใช้เพื่ออ้างถึงคำสั่งก่อนหน้า

ไม่กี่วิธีที่คุณสามารถจัดการกับสถานการณ์

ต่อไปนี้จะส่งออกสตริงตามที่เป็นอยู่

echo 'Reboot your instance!'

ต่อไปนี้จะดำเนินการคำสั่งและเชื่อมสตริง

echo 'escaping #'" adding `which python` to the string"
echo '#!'`which python`

1

ในbash 4.3ดูเหมือนว่าคุณไม่จำเป็นต้องใช้คำพูดเดียวหรือset +H:

$ bash --version
GNU bash, version 4.3.46(1)-release (x86_64-unknown-linux-gnu)
[...]
$ echo "Reboot your instance!"
Reboot your instance!

อาจเป็นข้อผิดพลาดเพราะที่นี่ฉันมี 4.4.12 และอีกครั้งฉันต้องการset +Hหรืออ้างถึง หรือคุณมีset +Hบางแห่ง (เช่นใน/etc/profile)
Bodo Thiesen

การใช้! -char ไม่ได้ที่ท้ายประโยคจะตรวจสอบการตรวจจับเหตุการณ์ของ bash ที่ยังทำงานได้ดี เวอร์ชันคือ 4.3.30 ........ $ echo "ตรวจสอบประโยคของคุณอีกครั้ง foo" bash
:!

0

คุณสามารถใช้heredoc :

cat <<EOF
Reboot your instance!
EOF

มันน่ารำคาญในกรณีนี้เพราะไม่ใช่ซับเดียว แต่สำหรับคำสั่งที่ยาวกว่า (เช่นการเขียนสคริปต์ทุบตี) มันใช้งานได้ดี

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