我一直认为 bash 在使用不带双引号或带双引号时对待反斜杠是一样的,但我错了:
[user@linux ~]$ echo "foo \ "
foo \
[user@linux ~]$ echo foo \ # Space after \
foo
所以我认为使用双引号时总是打印反斜杠,但是:
[user@linux ~]$ echo "foo \" "
foo "
[user@linux ~]$ echo "foo \\ "
foo \
为什么第一行代码中显示反斜杠?
答案1
仅当反斜杠后跟以下字符之一时,反斜杠才保留其特殊含义:'
$
'、'`
'、'"
'、'\
' 或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 周围的单引号替换为双引号。