如何躲过历史扩展感叹号

如何躲过历史扩展感叹号

本文介绍了如何躲过历史扩展感叹号!在双引号字符串中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

命令替换对于令人惊讶的行为不是必需的,尽管它是最常见的用例.同样的问题只适用于 echo "'!b'"

the command substitution is not necessary for the surprising behavior, although it is the most common use case. The same question applies to just 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 指出).
    • In the last example, what is the best way to escape the !?
    • Why was it not escaped even if I used single quotes, while echo "$(echo '$b')" was? What is the difference between ! and $?
    • Why was does echo $(echo '!b') (no quotes) work? (pointed by @MBlanc).
    • 我宁愿不这样做:

      • set +H 因为我之后需要 set -H 来维持 shell 状态

      • set +H as I would need set -H afterwards to maintain shell state

      反斜杠转义,因为我需要为每个 ! 设置一个,而且它必须在引号之外:

      backslash escapes, because I need one for every ! and it has to be outside the quotes:

      echo "$(echo '!a')"
      # '!a'.
      # No good.
      
      echo "$(echo 'a '!' b '!' c')"
      # a ! b ! c
      # Good, but verbose.
      

    • echo $(echo '!b')(无引号),因为命令可能返回空格.

    • echo $(echo '!b') (no quotes), because the command could return spaces.

      版本:

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

      推荐答案

      在上一个例子中,

      echo "$(echo '!b')"
      

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

      the exclamation point is not single-quoted. Because history expansion occurs so early in the parsing process, the single quotes are just part of the double-quoted string; the parser hasn't recognized the command substitution yet to establish a new context where the single quotes would be quoting operators.

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

      To fix, you'll have to temporarily turn off history expansion:

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

      这篇关于如何躲过历史扩展感叹号!在双引号字符串中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 08:34