题 什么是“-bash:!”:找不到事件“


尝试在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

任何人都可以解释什么是“bash事件?”我以前从未听过这个概念。另外,我该怎么输出“!”在句末?


88
2017-12-02 10:45






答案:


您可以使用关闭历史记录替换 set +H


40
2017-12-02 16:31



你知道语法背后的原因吗?这似乎真的反直觉。你认为你打字了 +H 启用某些东西 -H 禁用某些东西。 - PunkyGuy
@PunkyGuy:我不知道它背后的历史(双关语),但Unix选项通常以连字符(或减号)开头, + 与此恰恰相反。 - Dennis Williamson


! 是bash的特殊字符,它用于引用以前的命令;例如,

!rm

将调用并执行以字符串“rm”开头的最后一个命令,并且

!rm:p

将调用但不执行以字符串“rm”开头的最后一个命令。 bash正在解释感叹号 echo "reboot your instance!" 作为“在这里替换最后一个以感叹号后面的字符开头的命令“并且抱怨你在历史记录中找不到以单引号开头的事件(命令)。

尝试

echo reboot your instance\!

从bash中保护(逃避)感叹号。


86
2017-12-02 10:49



是的,但如果我想使用echo -e“某些文本$ ENV_VAL更多文本\ n立即启动!” ? - Maxim Veksler
写两个echo语句;你可以免费获得换行。 - MadHatter
简单的解决方案是一次使用单引号和双引号:echo -e“Text \ nReeboot”'!' - mmey
这很糟糕。如果我没有逃脱感叹号,bash会抛出一个合适的东西。如果我 做 逃避它,反斜杠包含在最后的字符串中。为什么这样做,Bash !! (pastebin.com/g4PYv56A) - Hubro
@Hubro公平,我不确定这都是bash的错。通过使用ruby来为bash提供东西,你有些复杂的事情,而且我不清楚ruby在剥离或强化转义字符时扮演的角色是什么。 - MadHatter


要解决原始问题,请尝试使用单引号,而不是双引号。对于后者,bash将在将结果传递给命令之前尝试扩展某些字符(在这种情况下为echo)。使用单引号,bash传递整个字符串,不变。

! 在命令中用于引用命令行历史记录。看到: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS 全套。通过上面的例子,bash正在尝试扩展 !" 作为对echo之前的事件的引用,因此是错误。

请注意,在脚本中, 所有 历史命令的禁用,因为它们只在交互式shell中有意义。

我经常使用的唯一一个是 !$。它扩展到上一个命令的最后一个参数。这是一个有用的速记。


22
2017-12-02 11:02



!! 填写完整的最后一个命令是非常有用的;尤其, sudo !! 要么 pfexec !! - jgoldschrafe
我也发现sudo和pfexec是很好的工具,但不需要那么热情。 - LeartS
$_ 比bash工作更多的shell,它是一个适当的变量,不像 !$。 (和@LeartS:我喜欢你的笑话缺少表情符号。;)) - ΤΖΩΤΖΙΟΥ


只是在它们之间放一个空格并“比它的工作。

干杯。


5
2017-09-25 07:06



您能否为您的解决方案的工作原理添加解释? - 200_success
这是有效的,因为Bash只对待!作为一个特殊字符,如果它直接后跟一个非空白字符。但是,它还会为您的输出添加额外的空白,因此可能并不总是需要... - mmey


是的,!是bash的特殊字符,它用于引用以前的命令。

几乎没有办法处理这种情况

以下将按原样输出字符串

echo 'Reboot your instance!'

以下将执行该命令并连接该字符串

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

2
2018-04-25 13:57





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!

1
2017-07-12 14:43



可能是一个错误,因为在这里,我有4.4.12而且我还需要 set +H 或引用。或者你有 set +H 在某个地方(比如 /etc/profile)。 - Bodo Thiesen
在句子末尾使用!-char验证bash的事件检测仍然正常。版本是4.3.30 ........ $ echo“重新检查你的句子!foo”bash:!foo:找不到事件 - JohnnyD92


你也可以使用 定界符

cat <<EOF
Reboot your instance!
EOF

在这种情况下很烦人,因为它不是单行,但对于更长的命令(比如写一个bash脚本),它的效果很好。


0
2017-07-07 11:41