bash - 如何逃脱历史扩展感叹号!在双引号字符串中?

标签 bash syntax quotes

编辑:对于令人惊讶的行为,命令替换不是必需的,尽管它是最常见的用例。同样的问题只适用于 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 "$(echo '\!a')"
    # '\!a'.
    # No good.
    
    echo "$(echo 'a '\!' b '\!' c')"
    # a ! b ! c
    # Good, but verbose.
    
  • echo $(echo '!b')(无引号),因为该命令可能会返回空格。

版本:

bash --version | head -n1
# GNU bash, version 4.2.25(1)-release (i686-pc-linux-gnu)

最佳答案

在你的最后一个例子中,

echo "$(echo '!b')"

感叹号不是单引号。因为历史扩展发生在解析过程的早期,所以单引号只是双引号字符串的一部分;解析器尚未识别命令替换以建立新的上下文,其中单引号将引用运算符。

要修复,您必须暂时关闭历史扩展:

set +H
echo "$(echo '!b')"
set -H

关于bash - 如何逃脱历史扩展感叹号!在双引号字符串中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22125658/

相关文章:

bash - 需要帮助替换 bash 脚本中的单引号

bash - 如何循环处理每个输出行?

regex - 在多个日志文件中查找模式?

mysql - Grep/Sed 替换大型 .sql 文件中的小文本

language-agnostic - 多参数切换语句

jquery 为多个元素语法设置 css

sql - 无法使用 sqldf 对 R 中的函数使用rank()

linux - shell 语法错误

shell - 子 Shell 中变量中的引号

Java Regex - 捕获引号之外的所有内容