Що таке "-bash:!": Подія не знайдена "


114

Спробуйте виконати наступне під оболонкою bash 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щось відключити.
Гевін Уорд

7
@PunkyGuy: Я не знаю історії (каламбур призначений) за нею, але параметри Unix, як правило, починаються з дефісу (або мінусу) і +є просто протилежним до цього.
Денніс Вільямсон

105

!є спеціальним символом для bash, він використовується для позначення попередніх команд; наприклад,

!rm

згадає та виконає останню команду, що розпочалась із рядка "rm", та

!rm:p

буде нагадувати, але не виконувати останню команду, що почалася з рядка "rm". bash інтерпретує знак оклику echo "reboot your instance!"як " заміну тут останньої команди, яка розпочалася із символу (ив) відразу після знака оклику ", і нарікає на вас, що він не може знайти подію (команду) у вашій історії, яка почалася з одного подвійна цитата.

Спробуйте

echo reboot your instance\!

для захисту (втечі) знака оклику від удару.


Так, але це має статися, якщо я хочу використовувати echo -e "трохи тексту $ ENV_VAL ще трохи тексту \ nЗавантажте зараз!" ?
Максим Векслер

1
Напишіть два ехо-заяви; ви отримуєте підписку на лінії безкоштовно.
MadHatter

1
Просте рішення - використовувати одиничні лапки та подвійні лапки відразу: echo -e "Text \ nReeboot" '!'
mmey

4
Це смокче. Якщо я не ухиляюся від оклику, Баш кидає форму. Якби я зробити дінешся, зворотний слеш включається в кінцевій рядку. Чому ти це робиш, Баш !! ( pastebin.com/g4PYv56A )
Hubro

2
@Hubro чесно, я не впевнений, що в цьому вся вина. У вас є дещо складні питання, використовуючи рубін, щоб подавати речі на башти, і мені незрозуміло, яку роль грає рубін у зніманні або посиленні втечі символів.
MadHatter

25

Щоб вирішити свою первісну проблему, спробуйте скористатися одинарними цитатами, а не подвійними лапками. З останнім, bash намагатиметься розширити певні символи, перш ніж передавати результат команді (відлуння в цьому випадку). За допомогою одиничних лапок, bash передає весь рядок, незмінним.

!використовується в командах для посилання на історію командного рядка. Дивіться: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS для повного набору. З вищенаведеним прикладом, bash намагається розширити !"як посилання на подію, перш ніж ехо потрапить, отже, помилка.

Зауважте, що в скриптах усі команди історії вимкнено, оскільки вони мають сенс лише в інтерактивній оболонці.

Єдиним, яким я користуюся регулярно, є !$. Він розширюється до останнього аргументу попередньої команди. Це корисна стенограма місцями.


4
!!заповнити останню введену команду надзвичайно корисно; зокрема, sudo !!абоpfexec !!
jgoldschrafe

2
Я також вважаю, що sudo та pfexec є хорошими утилітами, але не потрібно бути таким ентузіазмом.
LeartS

$_працює в більшості оболонок, ніж bash, і це правильна змінна, на відміну від !$. (і @LeartS: мені сподобалася відсутність смайлів у вашому жарті.;))
ΤΖΩΤΖΙΟΥ

7

Просто поставте пробіл між собою! і "ніж це буде працювати.

Ура.


2
Не могли б ви додати пояснення, чому працює ваше рішення?
200_успіх

2
Це працює, тому що Баш тільки лікує! як спеціальний символ, якщо за ним безпосередньо слідує символ, який не є пробілом. Однак це також додасть додатковий пробіл у ваш висновок, так що не завжди може бути бажаним ...
mmey

2

Так, ! є спеціальним символом для bash, він використовується для позначення попередніх команд.

Мало хто з способів вирішити ситуацію

Далі буде виведено рядок таким, яким він є

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).
Бодо Тісен

Використання! -Char не в кінці речення підтверджує, що виявлення події bash все ще працює добре. Версія 4.3.30 ........ $ echo "Перевірте свій вирок! Foo" bash
:!

0

Ви також можете використовувати гередок :

cat <<EOF
Reboot your instance!
EOF

Це дратує в цьому випадку, оскільки це не однолінійний, але для довших команд (наприклад, написання bash-скрипту), це чудово працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.