编辑:命令替换对于令人惊讶的行为并不是必要的,尽管它是最常见的用例。同样的问题也适用于echo "'!b'"
b=a
# Enable history substitution.
# This option is on by default on interactive shells.
set -H
echo '!b'
# Output: '!b'
# OK. Escaped by single quotes.
echo $(echo '!b')
# Output: '!b'
# OK. Escaped by single quotes.
echo "$(echo '$b')"
# Output: '$b'
# OK. Escaped by single quotes.
echo "$(echo '!b')"
# Output: history expands
# BAD!! WHY??!的最佳方法是什么?echo "$(echo '$b')"是单引号),它也没有逃脱呢?!和$有什么区别?echo $(echo '!b') (没有引号)起作用?(由@MBlanc指出)。我宁愿这样做而不:
set +H,因为之后我需要set -H来维护shell状态。!我都需要一个反斜杠,它必须在引号之外:
回显$( echo '!a')“#!a‘。不太好。回音$(回叫'a '!‘B '!’C‘)#a!B!C#很好,但很详细。echo $(echo '!b') (没有引号),因为命令可以返回空格。版本:
bash --version | head -n1
# GNU bash, version 4.2.25(1)-release (i686-pc-linux-gnu)发布于 2014-03-02 17:19:42
在最后一个例子中,
echo "$(echo '!b')"感叹号不是单引号。因为历史扩展发生在解析过程的早期,所以单引号只是双引号字符串的一部分;解析器还没有识别命令替换以建立一个新的上下文,其中单引号将引用操作符。
要解决这个问题,您必须暂时关闭历史扩展:
set +H
echo "$(echo '!b')"
set -H发布于 2016-12-22 00:04:17
这被反复报告为一个bug,最近一次是在2014年针对bash4.3,因为行为可以追溯到bash 3。。
有一些讨论,这是一个错误,或预期,但可能是不受欢迎的行为;似乎大家的共识是,无论你想要描述的行为,它不应该被允许继续。
它在bash4.4中是固定的,echo "$(echo '!b')"没有展开,echo "'!b'"有,我认为这是正确的行为,因为单引号是第一个示例中的shell语法标记,而不是第二个示例中的shell语法标记。
发布于 2014-03-02 11:17:00
如果启用了历史扩展,则只有将!字符放入单引号、转义或后跟空格字符、回车或=时才能回显它。
来自man bash
Only backslash (\) and single quotes can quote the history
expansion character.
Several characters inhibit history expansion if found immediately fol-
lowing the history expansion character, even if it is unquoted: space,
tab, newline, carriage return, and =.我相信这里的关键词是“只有”。问题中提供的例子只考虑最外层的引号是双引号。
https://stackoverflow.com/questions/22125658
复制相似问题