为什么`echo -e“ \\\ SOME_TEXT”`只显示一个反斜杠?


19

有人可以解释一下Linux shell中字符转义背后的情况吗?我尝试了以下内容并进行了很多搜索,但没有成功了解正在发生的事情(以及如何发生):

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案例有什么不同?

我感谢对前几行所做的任何解释。


echo -e行为不是标准定义的-请参阅pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html。如果输入中的任何地方都有文字反斜杠,则输出完全由实现定义,并且唯一允许的选项是-n(这表示符合标准的实现将在其输出上echo -e打印出来-e)。
Charles Duffy

...即使您100%确信shell是bash,即使这样 echo -e也不安全:echo如果同时启用了运行时选项posixxpg_echo使用等效的构建时选项进行编译,则将按照标准运行。安全的做法是printf改用-请参阅上面链接的“应用程序使用情况”和“ RATIONALE”部分,介绍如何printf使用代替echo
Charles Duffy

Answers:


28

这是因为bashecho -e相结合。从man 1 bash

不带引号的反斜杠(\)是转义字符。它会保留下一个字符的字面值,但除外<newline>。[…]

在双引号包围的字符保留了引号中的所有字符的字面意义,例外$,`,\[...]的反斜杠只有后面时,通过下列字符中的一个特殊含义:$`, ,"\<newline>

关键是:双引号反斜杠并不总是很特殊。

通常有多种实现echo,它是内置的bash;这里重要的是这种行为:

如果-e有效,将识别以下序列:
\\
反斜杠
[…]
\n
新行

现在我们可以解码:

  1. echo -e "\ Hello!"–没什么特别的bash,没什么特别的echo\留下来。
  2. echo -e "\\ Hello!"–第一个\说从字面上看待bash第二个\echo获取\ Hello!并按上述方式操作。
  3. echo -e "\\\ Hello!"–第一个\说从字面上看待bash第二个\echo得到\\ Hello!并且(由于-e)被识别\\\
  4. echo -e "\\\\ Hello!"–第一个\说从字面上看待bash第二个\;第三个人与第四个人相同。echo得到\\ Hello!并且(由于-e)被识别\\\
  5. echo -e "\\\\\ Hello!"–第一个\说从字面上看待bash第二个\;第三个人与第四个人相同。最后一个不特殊;echo获取\\\ Hello!和(由于-e)它会将首字母识别\\\,最后一个\保留完整。

等等。如您所见,最多四个连续的反斜杠给出一个。这就是为什么您(至少)需要9个才能得到3个的原因。9 = 4 + 4 + 1。

现在\n

  1. echo -e "\n Hello!"–没什么特别的bash,echo获得相同的字符串,并且(由于-e)将其解释\n为换行符。
  2. echo -e "\\n Hello!"bash解释\\\echo得到\n Hello!和结果与上面相同。
  3. echo -e "\\\n Hello!"bash将首字母解释\\\echo获取\\n Hello!和(由于-e)将其解释\\\需要打印的文字。

如果'不是"(由于不同的bash行为)或没有-e(不同的echo行为),结果将是不同的。


1
非常感谢你!因此,有两个转义步骤,一个是bash进行的转义步骤,另一个是-e通过bash判断的文本进行转义的步骤,对吗?如果那是正确的,那就消除了混乱。您能否提及一下sed行为方式?它有自己的内置逃生技术吗?所以我的意思是它的行为像echo with -e吗?
Mohammed Noureldin

2
@MohammedNoureldin是的,有两个步骤。您最初的问题就可以了,不要让它过于复杂sed。但是,您可能会问另一个问题(sed仅关于),只需先进行自己的研究即可。
卡米尔Maciorowski

3
@MohammedNoureldin sed将遵循相同的基本原理:bash将根据其规则解释命令行,解析(并可能删除)引号和转义符。结果将传递给sed,后者根据转义规则对其进行解释。顺便说一句,您可以通过在中使用单引号字符串来简化此操作bash,因为这并没有完成eny转义解释(通过bash进行)-bash删除了单引号,并将其中的内容直接传递给命令。
戈登·戴维森

echo -e "\\\n Hello!"万一我还有一个小问题。bash将在此处进行转义,并成为转义符,\\n然后-e将其转义为两个反斜杠\\n,然后变为\n。现在谁来诠释\n新路线?通常情况下echo -e "\n Hello!",bash不执行任何操作,并-e解释\n为换行符。但是在第一个提到的情况下,解释过程是在\n获得解释之前完成的。你能解释一下吗?
Mohammed Noureldin

1
好的,我的错,关于他们的夜晚,我已经读了两天了,因此,显然我开始混在一起,我相信昨晚还有其他令sed我困惑的事情(也许昨天我做错了),但是现在我再次尝试与echo -e和进行相同的操作sed,我得到了与除外相同的东西,谢谢!
Mohammed Noureldin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.