Что такое «-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

Кто-нибудь может объяснить, что такое "события bash"? Я никогда не слышал эту концепцию раньше. Кроме того, как я должен вывести "!" в конце предложения?

Ответы:


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\!

защитить (убежать) восклицательный знак от bash.


Да, но это должно произойти, если я хочу использовать echo -e "некоторый текст $ ENV_VAL, еще текст \ nПерезагрузить сейчас!" ?
Максим Векслер

1
Напишите два эхо-заявления; Вы получаете бесплатный перевод.
MadHatter

1
Простое решение - использовать одинарные и двойные кавычки одновременно: echo -e "Text \ nReeboot" '!'
Ммей,

4
Это отстой. Если я не уйду от восклицательного знака, Баш бросит приступ. Если бы я сделать денешься, обратный слеш включается в конечной строке. Почему ты это делаешь, Баш! ( pastebin.com/g4PYv56A )
Хабро

2
@ Честно говоря, я не уверен, что это вина Бэша. У вас есть несколько сложных вопросов, когда вы используете ruby ​​для подачи вещей в bash, и мне не ясно, какую роль играет ruby ​​в раздевании или усилении escape-персонажей.
MadHatter

25

Чтобы решить исходную проблему, попробуйте использовать одинарные кавычки, а не двойные. В последнем случае bash будет пытаться расширить определенные символы перед передачей результата в команду (в данном случае echo). В одинарных кавычках bash передает всю строку без изменений.

!используется в командах для ссылки на историю командной строки. Смотрите: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS для полного набора. В приведенном выше примере bash пытается раскрыться !"как ссылка на событие до того, как эхо просматривает его, отсюда и ошибка.

Обратите внимание, что в сценариях все команды истории отключены, поскольку они имеют смысл только в интерактивной оболочке.

Единственное, что я использую на регулярной основе, это !$. Он расширяется до последнего аргумента предыдущей команды. Это полезное сокращение местами.


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

2
Я также нахожу sudo и pfexec хорошими утилитами, но не нужно быть таким восторженным.
Начало

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

7

Просто поставьте пробел между! и "чем это будет работать.

Приветствия.


2
Не могли бы вы добавить объяснение, почему ваше решение работает?
200_успех

2
Это работает, потому что Bash только лечит! как специальный символ, если за ним непосредственно следует непробельный символ. Тем не менее, это также добавит дополнительный пробел к вашему выводу, так что это не всегда может быть желательным ...
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:! Foo: событие не найдено
JohnnyD92

0

Вы также можете использовать heredoc :

cat <<EOF
Reboot your instance!
EOF

Это раздражает в этом случае, потому что это не однострочный текст, а для более длинных команд (например, написание скрипта bash), он отлично работает.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.