为什么使用引号时显示单个反斜杠

为什么使用引号时显示单个反斜杠

我一直认为 bash 在使用不带双引号或带双引号时对待反斜杠是一样的,但我错了:

[user@linux ~]$ echo "foo \ "
foo \
[user@linux ~]$ echo foo \ # Space after \
foo

所以我认为使用双引号时总是打印反斜杠,但是:

[user@linux ~]$ echo "foo \" "
foo "
[user@linux ~]$ echo "foo \\ "
foo \

为什么第一行代码中显示反斜杠?

答案1

部分3.1.2.3 双引号GNU Bash 手册说:

仅当反斜杠后跟以下字符之一时,反斜杠才保留其特殊含义:' $'、' `'、' "'、' \' 或 newline。在双引号内,后跟这些字符之一的反斜杠将被删除。前面没有特殊含义的反斜杠字符保持不变。双引号可以在双引号内引用,方法是在双引号前面加上反斜杠。如果启用,将执行历史扩展,除非!使用反斜杠转义出现在双引号中的“ ”。 ' ' 前面的反斜杠!不会被删除。

因此,\双引号中的处理方式与\单引号和\外部引号中的处理方式不同。它按字面处理,除非它处于导致按字面处理的字符的位置,否则该字符可能在双引号中具有特殊含义。

\'请注意,像、\?、 和 这样的序列\*按字面意思处理,并且反斜杠不会被删除,因为'?*当用双引号括起来时已经没有特殊含义。

答案2

反斜杠根据上下文有不同的解释:

  • 在双引号内(您的第一个示例):

    The backslash  retains its special meaning  only when followed
    by one of the following characters: $, `, ", \, or <newline>.
    
  • 不带引号(你的第二个例子):

    A  non-quoted  backslash  (\)  is the  escape  character.   It
    preserves  the  literal  value  of  the  next  character  that
    follows,  with the  exception of  <newline>.  If  a \<newline>
    pair  appears, and  the backslash  is not  itself quoted,  the
    \<newline> is treated  as a line continuation (that  is, it is
    removed from the input stream and effectively ignored).
    
  • 使用构造$'....',您可以在引号内使用标准退格字符,几乎与 C 中一样。例如\n,\t等。

  • 使用反引号:

    When  the old-style  backquote form  of substitution  is used,
    backslash retains its literal  meaning except when followed by
    $, `, or \.
    

引用来源:bash手册

答案3

这是一个“为了理解而复杂化”的例子。希望它对其他试图理解引号和反斜杠的人有所帮助。

在此示例中,我想重复该模式 3 次。

>~# echo 'ABC\n\t'
ABC\n\t

使用单引号,这相当简单:

>~# echo 'ABC\n\t' | sed -e 's#ABC\\n\\t#ABC\\n\\tABC\\n\\tABC\\n\\t#'
                                  ↑  ↑      ↑        ↑  ↑     ↑  ↑
                    # These backslashes escaped by sed
ABC\n\tABC\n\tABC\n\t

这是使用的方法双引号:(再次,为了理解而复杂)

>~# echo 'ABC\n\t' | sed -e "s#ABC\\\n\\\t#$(printf '%0.sABC\\\\n\\\\t' $(seq 1 3))#"
                                  ↑   ↑                     ↑ ↑  ↑ ↑
            # These backslashes are removed in double quotes. Showing intermediate stage:

>~# echo 'ABC\n\t' | sed -e "s#ABC\\n\\t#$(printf '%0.sABC\\n\\t' $(seq 1 3))#"

                # Expanding printf results in:

>~# echo 'ABC\n\t' | sed -e 's#ABC\\n\\t#ABC\\n\\tABC\\n\\tABC\\n\\t#'

ABC\n\tABC\n\tABC\n\t

只是为了玩弄并掌握引号和反斜杠,请将 printf 周围的单引号替换为双引号。

相关内容