有人能解释一下 Linux shell 中字符转义的幕后情况吗?我尝试了以下操作,并在 Google 上搜索了很多,但还是没能理解发生了什么(以及如何发生):
root@sv01:~# echo -e "\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\\ Hello!"
\\\ Hello!
root@sv01:~# echo -e "\n Hello!"
Hello!
root@sv01:~# echo -e "\\n Hello!"
Hello!
root@sv01:~# echo -e "\\\n Hello!"
\n Hello!
我完全迷失了,例如,为什么三个反斜杠只会产生一个反斜杠?我期望:前两个将被转义为一个,第三个将找不到任何可转义的内容,因此它将保留为斜线(第一个实验中的线),但实际发生的情况是,第三个消失了。
为什么我从四个中得到一个反斜杠\\\\ Hello
?我希望每对都会给出一个反斜杠 -> 两个反斜杠。
为什么在最后一种情况下我需要三个反斜杠才能转义 \n?转义的背景下发生了什么?它与\\n
案例有何不同?
我很感激对前面几行发生的事情的任何解释。
答案1
这是因为bash
和 的echo -e
结合。从man 1 bash
未加引号的反斜杠 (
\
) 是转义字符。它保留后面下一个字符的字面值,但 除外<newline>
。[…]将字符括在双引号中会保留引号内所有字符的字面值,但以下字符除外:、、、
$
[ …] 反斜杠仅当后面跟着以下字符之一时才保留其特殊含义:、、、、或。`
\
$
`
"
\
<newline>
要点是:双引号反斜杠并不总是特殊的。
一般来说,有各种实现echo
,它是内置的bash
;这里重要的是这种行为:
如果
-e
有效,则识别以下序列:
\\
反斜杠
[…]
\n
换行
现在我们可以解码:
echo -e "\ Hello!"
– 对 来说没什么特别的bash
,对 来说没什么特别的echo
;\
留下来。echo -e "\\ Hello!"
– 第一个\
告诉从字面上bash
看待第二个;获取并按上述方式操作。\
echo
\ Hello!
echo -e "\\\ Hello!"
– 第一个\
告诉从字面上bash
看待第二个\
;echo
得到\\ Hello!
并且(因为-e
)它识别\\
为\
。echo -e "\\\\ Hello!"
– 第一个\
告诉bash
要从字面上看待第二个\
;第三个告诉要从字面上看待第四个;echo
得到\\ Hello!
并且(因为-e
)它识别\\
为\
。echo -e "\\\\\ Hello!"
– 第一个\
告诉bash
要按字面意思对待第二个\
;第三个告诉要按字面意思对待第四个;最后一个并不特殊;echo
得到\\\ Hello!
并且(因为-e
)它将首字母识别\\
为\
,最后一个\
保持不变。
依此类推。如您所见,最多四个连续的反斜杠会给出结果 1。这就是为什么您需要 (至少) 九个反斜杠才能得到 3。9=4+4+1。
现在有\n
:
echo -e "\n Hello!"
– 没有什么特别的bash
,echo 获取相同的字符串并且(因为-e
)它将其解释\n
为换行符。echo -e "\\n Hello!"
–bash
解释\\
为\
;echo
得到\n Hello!
并且结果与上面相同。echo -e "\\\n Hello!"
–bash
将首字母解释\\
为\
;echo
得到\\n Hello!
并且(因为-e
)它解释为需要打印的\\
文字。\
'
如果有"
(由于bash
行为不同)或者没有-e
(由于行为不同),结果会有所不同echo
。