在bash中,如何逃脱感叹号?


183

我想做类似的事情bzr commit -m "It works!"。我可以通过这样做来逃避感叹号bzr commit -m "It works\!"。但是,然后我的提交消息包括反斜杠。在仍然忽略反斜杠的同时,如何逃避感叹号?


1
bzr commit -m "It works"!也在做作品。
kba

1
正如我在您放置的命令之前实际指出的那样,它本身是可以工作的:)bzr commit -m "It works!"
h4unt3r 2014年


1
尽管可以接受的答案是解决提交问题的一个不错的解决方法,但我认为这并不是对实际问题的答案:Bash历史记录扩展。请考虑接受丹尼斯的回答吗?
Arjan 2015年

Answers:


153

由于您不依赖bash扩展提交消息中的变量,因此可以改用单引号。bash不会扩展单引号中的字符串。

bzr commit -m 'This does work!' 

24
由于问题是“我如何逃避感叹号?” 而不是“我如何不扩展感叹号?” 我认为这是不正确的。在某些情况下(例如,在同一命令行中使用撇号和感叹号时),这是行不通的。下面的答案可以更好地满足许多人的需求。
Jann

7
@Jann:您对此是100%正确的,但是我认为这里的问题是有关超级用户的很多问题:我们是在一定程度上回答这个问题,还是在帮助人们解决他们的特定问题。我认为这两种方式都有用,这是在寻求特定问题的帮助。
本杰明·班尼尔

碰!这是一个特定的问题。我只是想对我的问题做出回答,以便能够在许多情况下使用。PS:我什至提到这是因为我需要同时将撇号和感叹号传递给Perl程序,并且需要以下解决方案。:)
Jann

我同意本杰明和詹恩的意见,但投了反对票。搜索引擎对问题的标题进行了索引,这就是我来这里的原因,而且可能大多数用户都来过这里。这就是为什么我认为重要的是,实际问题反映出背后的问题。在其他论坛中,建议人们(几乎被迫)准确询问他们要寻找的东西。回答表达不佳的问题会支持草率,这就是我在这里投票的确切原因。作为一种折衷/解决方案,我的建议是帮助调整标题,以便反映实际问题。
ChristophK,

153

如果您想要双引号和感叹号,这是另一种方法:

echo "It's broken"'!'

即使!不在行尾,此方法也有效。

例如:

echo "hello there"'!'" and goodbye"

奖励:可以使用类似的技术(在sed的帮助下)对Sh或Bash中的任何文本进行转义:请参阅此答案中的第一个选项。此外,如果已bash-completion安装,则quote()功能可能已经可用。


4
很好的提示,JWD。我不知道bash字符串可以简单地通过省略它们之间的空格来连接。
艾伦·H。

实际上,如果感叹号位于字符串的末尾,那么您可以echo "Happy birthday!"按预期的方式正常工作,否则可以用反斜杠将其转义,但是反斜杠也将被打印出来,XD Bash并不适合胆怯的人:)
h4unt3r 2014年

@ h4unt3r:奇怪,这不是我的经验。对我来说,echo "Happy Birthday!"输出2行。第一个是echo "Happy birthday"(无感叹号),第二个是“生日快乐”(再次,无感叹号)。进行此测试时,是否打开了历史记录扩展?
jwd

@jwd您正在运行什么版本的bash?我一直在发展历史。你不小心用了两个!为您测试?
h4unt3r 2014年

@ h4unt3r:,version 4.1.2(1)-release (x86_64-redhat-linux-gnu)肯定只有一个!被使用。我histexpand进来了$SHELLOPTS。但是,我只是尝试在另一台机器上尝试4.3.18(2)-release,它的行为与您描述的相同。我猜这是一个已修复的错误。
2014年

66

关闭历史记录扩展

set +H

要么

set +o histexpand

~/.bashrc如果通常不使用历史记录扩展,则可以向其中添加这些命令之一。

Bash 4.3添加了一个特例

如果历史记录扩展字符在双引号字符串中紧接在双引号之前,则也将其视为带引号


谢谢-这行得通,但我必须这样做set +o histexpand,而不是set -o histexpand。您可以编辑答案来解决此问题吗?
马修2010年

糟糕,错字,对不起。固定。
丹尼斯·威廉姆森

优秀!一直在寻找适合年龄的...。作为转义将无法工作...我也不想使用单引号...我将其添加到我的.bashrcthx !!中,从未!在脚本中使用过!总是令人不安...
水瓶座力量

太棒了!echo "@AquariusPower!"
joehanna

12

使用单引号(')而不是双引号(“)。单引号会关闭其中所有内容的解释,而双引号只会关闭部分内容。

bzr commit -m 'It works!'

4

我刚刚发现了另一种方法,至少可以echo处理您想用感叹号插入的字符串(句子)。它或多或少地围绕Bash histexpand进行了最终运行,并且只花了一点点时间进行编码。

http://www.ascii-code.com/上列出的,感叹号的十六进制为 21,因此,如果将\x21字符串放在末尾,请echo -e $foo进行$foo自己的扩展回显[ie foo=$(echo -e "$foo")],即echo $foo再次获取时,!将以结尾的字符串获取。而且也没有切换histexpand。

在Bash 4+中肯定可以工作。早期版本,ymmv。


嗯,这对我不起作用。
lzap 2014年

我不明白你在说什么回声。'echo -e'和'printf'解释转义的八进制,十六进制和Unicode代码。如果您使用其中任何一个,则可以使用“ \ 041”(八进制表示“!”)或“ \ x21”(十六进制)代替感叹号。例如:printf "OMG\041"。如果要在不是echo或printf的地方构建双引号的字符串(如OP询问的提交字符串),则可以将其嵌入$(echo -e "\041")在感叹号所在的字符串中。像这样:bzr commit -m "This is a great commit$(echo -e "\041")"
托德·沃尔顿
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.