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


113

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

谁能解释什么是“流行事件”?我以前从未听过这个概念。另外,我应该如何输出“!” 在句子的结尾?

Answers:


53

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


2
您知道语法背后的原因吗?似乎真的很直觉。您可能会想键入+H以启用和-H禁用某些功能。
加文·沃德

7
@PunkyGuy:我不知道其背后的历史记录(双关语的意思),但是Unix选项通常以连字符(或减号)开头,+与之相反。
丹尼斯·威廉姆森

103

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

!rm

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

!rm:p

将调用但不执行以字符串“ rm”开头的最后一条命令。bash将感叹号解释echo "reboot your instance!"为“ 在此处替换以感叹号之后的字符开头的最后一个命令 ”,并对您抱怨道,它在您的历史中找不到以单个字符开头的事件(命令)双引号。

尝试

echo reboot your instance\!

保护(避免)bash感叹号。


是的,但是如果我想使用echo -e“某些文本$ ENV_VAL一些文本\ n立即重新启动,则应该发生!” ?
Maxim Veksler 2010年

1
编写两个echo语句;您可以免费获得换行符。
MadHatter

1
简单的解决方案是一次使用单引号和双引号:echo -e“ Text \ nReeboot”'!'
mmey 2014年

4
糟透了 如果我不逃避感叹号,bash会合身。如果我确实将其转义,则最后一个字符串中将包含反斜杠。你为什么要这样做,巴什!(pastebin.com/g4PYv56A
Hubro

2
公平地说,@ Hubro,我不确定这都是bash的错。通过使用红宝石将东西喂入bash中,您遇到了一些复杂的事情,我不清楚红宝石在脱逃或增强转义符中起什么作用。
MadHatter

25

若要解决您的原始问题,请尝试使用单引号而不是双引号。对于后者,bash将尝试扩展某些字符,然后再将结果传递给命令(在本例中为echo)。bash使用单引号将整个字符串传递不变。

!在命令中用于引用命令行历史记录。请参阅:http : //tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS以获取全套。在上面的示例中,bash试图!"在回声进入之前扩展作为对事件的引用,从而导致错误。

请注意,在脚本中,所有历史记录命令均被禁用,因为它们仅在交互式外壳中才有意义。

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


4
!!填写最后输入的完整命令非常有用;特别是,sudo !!pfexec !!
jgoldschrafe 2010年

2
我还发现sudo和pfexec是很好的实用程序,但不必那么热心。
LeartS 2014年

$_与bash相比,它在更多的shell中工作,并且与相比,它是一个适当的变量!$。(和@LeartS:我喜欢您的笑话没有表情符号。;))
ΤZnΩΤZΙΟΥ16

7

只需在它们之间放一个空格!和“,它将起作用。

干杯。


2
您能否添加一个关于您的解决方案为何有效的解释?
200_success 2014年

2
这是有效的,因为Bash只对待!如果它后面紧跟非空格字符,则将其作为特殊字符。但是,它也会在输出中添加额外的空白,因此可能并不总是需要...
mmey 2014年

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)。
Bodo Thiesen

在句子的末尾使用!-char可以验证bash的事件检测仍然可以正常工作。版本是4.3.30 ........ $ echo“重新检查您的句子!foo” bash:!foo:未找到事件
JohnnyD92 '18

0

您也可以使用heredoc

cat <<EOF
Reboot your instance!
EOF

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.