为什么“ echo -e”命令似乎无法产生正确的输出?


21

在Ubuntu 18.04 LTS的终端中,当我编写此命令时:

echo -e "Hello\\\n"

将其作为输出:

Hello\n

但它应该打印,如手册页所述:

Hello\

也就是说,先打印Hello,然后是\,然后是换行符(然后是另一个换行符)。问题出在哪里?

请参阅以下几个echo -e命令及其输出

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n

是的。对于第一个2 \,它应该输出一个\。,最后一个\和n进行反斜杠转义\ n(新行)。所以为什么要打印Hello \
yolin00

1
尝试不使用引号。
ajgringo619

2
Eliah Kagan提供了一个了不起的答案,您应该接受。

2
首先不要使用echo:使用printf
chepner

2
如果要确保编写的内容恰好是作为参数传递给命令的内容,请始终使用单引号引起来。
Giacomo Alzetta

Answers:


29

反斜杠由特殊处理echo -e,但是首先,根据外壳的引用规则,它们有时由外壳(在本例中为bash)进行特殊处理。

echo实际看到的参数是Hello\\n因为您已传递-eecho,所以它特别对待反斜杠转义,并将\\其折叠为一个\。决赛n没有逃脱,所以从字面上看。

这样做的原因是,在操作echo自身之前和与之分离之前,shell 在某些情况下\特别对待,而在其他情况下则不会。未加引号\字符总是经过特殊处理的,单引号 \都从来没有经过特殊处理,但处理的双引号 \字符,如您运行的命令,是更加微妙和复杂。

当shell遇到一个命令双引号的文本,如"Hello\\\n",它把\作为转义字符时,它先于自身可以有内部双引号特殊意义的字符,而不是其他

  1. 因为\有时在内部有特殊的含义""\所以紧接在另一个前面的a \具有引用该第二的效果\。因此,在双引号内,第一个双引号\\会折叠成\
  2. 在前两个\字符之后,是第三个\字符,该字符不受前两个字符的影响,并且在之前n。但是n不是在双引号内曾经被特殊对待的字符,因此\在这种情况下之前就没有特殊对待。因此\n留下来\n

结果是,用双引号\\\n将其解释为\\n

echo -e看到时\\n,第一个\从第二个中删除特殊含义,因此echo按原义打印\n该文本。


如果您的目标是Hello使用额外的换行符但不加反斜杠进行打印(这个问题本来就模棱两可,再加上我认为这是一个有用的示例),那么一种解决方案是删除\。运行echo -e "Hello\\n"输出Hello时,在末尾使用额外的换行符。

更好的解决方案是使用单引号和write echo -e 'Hello\n'。单引号是最强的报价形式。通常,甚至可以使用更好的解决方案,printf而不是echo在这种情况下printf 'Hello\n\n'

如果您的目标是打印Hello\包括反斜杠,然后再加上一个换行符,则双引号方法是可行的,但麻烦。要弄清楚,工作向后:echo -e转换\\\\n双引号转换成换行,\\\,这样你就可以有六个反斜杠(这样做echo -e "Hello\\\\\\n"),因为\\n转弯到\n由于一个反斜杠另一个。您也可以使用5,因为\n\不转义时会保留双引号。

这说明了单引号的好处:只需将要echo -e查看的内容放在单引号(echo -e 'Hello\\\n')内。printf这里也很好。一种选择是printf 'Hello\\\n\n'。但是printf真正的亮点是您可以插入其他参数。您可以使用printf '%s\n\n' 'Hello\'插入第二个参数(实际上是Hello\因为单引号不会改变任何内容)来代替%s

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.