如何逃脱历史扩展感叹号!一个双引号&QUOT内;命令替换像" $('!B'回声)QU​​OT ;? [英] How to escape history expansion exclamation mark ! inside a double quoted " command substitution like "$(echo '!b')"?

查看:121
本文介绍了如何逃脱历史扩展感叹号!一个双引号&QUOT内;命令替换像" $('!B'回声)QU​​OT ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:命令取代是不必要的令人惊讶的行为,尽管它是最常见的情况。同样的问题也适用于刚回声'!B'

  B = A#开启历史替换。
#此选项在默认情况下交互shell。
设置-H呼应'!B'
#输出:'B'
# 好。单引号逃脱。回声$(回声'!B')
#输出:'B'
# 好。单引号逃脱。回声$(回声$ B')
#输出:'$ B'
# 好。单引号逃脱。回声$(回声'!B')
#输出:历史扩张
#BAD!为什么??


  • 在最后一个例子,什么是逃避的最佳方法

  • 为什么它没有逃过即使我使用单引号,而回声$(回声$ B')是?是什么区别 $

  • 为什么不回声$(回声'!B')(不含引号)工作? (由@MBlanc指出)。

我想preFER为此而不:


  • 设置+ H ,因为我需要设置-H 之后维持外壳的状态。


  • 反斜杠,因为我需要一个每次 键,它必须是引号外!

     回声$(回声'\\!A')
    # '\\!一个'。
    # 不好。回声$(回声'一'\\!'B'\\!'C')
    # 一个 ! b! C
    #好,但冗长。


  • 回声$(回声'!B')(不含引号),因为该命令可以返回的空间。


版本:

 的bash --version |头-n1
#GNU的bash,版本4.2.25(1) - 释放(i686的-PC-Linux的GNU)


解决方案

在您的最后一个例子,

 回声$(回声'!B')

感叹号不是单引号。由于历史扩展在分析过程中这么早时,单引号都只是双引号字符串的一部分;解析器无法识别命令替换尚未建立起一个新的上下文,其中单引号会被引用的运营商。

要解决,你必须暂时关闭历史扩展:

 集+ H
回声$(回声'!B')
设置-H

EDIT: 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??

  • 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).

I would prefer to do this without:

  • 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') (no quotes), because the command could return spaces.

Version:

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

解决方案

In your last example,

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

这篇关于如何逃脱历史扩展感叹号!一个双引号&QUOT内;命令替换像" $('!B'回声)QU​​OT ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆