在 Ubuntu 18.04 LTS 的终端中,当我编写此命令时:
echo -e "Hello\\\n"
它给出了这个作为输出:
Hello\n
但它应该打印,正如手册页所说:
Hello\
也就是说,首先是 print 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
根据 shell 的引用规则,反斜杠由 特殊处理
echo -e
,但首先它们有时由 shell(在本例中为)特殊处理。bash
echo
实际看到的说法是Hello\\n
。因为你已经传递-e
到echo
,所以它特别对待反斜杠转义,并被\\
折叠成一个\
。finaln
没有被转义,所以它按字面意思出现。这样做的原因是,在其自身的操作之前并且独立于
echo
自身的操作,shell在某些情况下会进行特殊处理\
,但在其他情况下则不会。不带引号的\
字符总是被特殊处理,单引号\
从不被特殊处理,但是双引号\
字符的处理,就像你运行的命令一样,更加微妙和复杂。当 shell 在命令中遇到双引号文本时,例如,当它位于一个在双引号内本身可以具有特殊含义的字符之前
"Hello\\\n"
,它会被视为转义字符,否则不会。\
\
有时在里面有一个特殊的含义,紧接在另一个之前""
的 a具有引用那一秒的效果。所以在双引号内,第一个被折叠成.\
\
\
\\
\
\
字符之后,第三个\
字符不受前两个字符的影响,并且位于n
. 但是n
不是一个在双引号内被特殊对待的字符,所以\
在这种情况下它之前没有被特殊对待。就这样\n
留下来\n
。效果是,在双引号中,
\\\n
被解释为\\n
.当
echo -e
sees时\\n
,第一个\
从第二个中删除特殊含义,因此按字面意思echo
打印\n
该文本。如果您的目标是打印
Hello
一个额外的换行符但没有反斜杠(这个问题最初是模棱两可的,而且我认为这是一个有用的例子),那么一个解决方案是删除一个\
. 最后运行带有额外换行符的echo -e "Hello\\n"
输出。Hello
更好的解决方案是使用单引号并写入
echo -e 'Hello\n'
. 单引号是最强的引用形式。一个更好的解决方案通常是使用printf
而不是echo
,在这种情况下是printf 'Hello\n\n'
。如果您的目标是打印
Hello\
包括反斜杠,后跟一个额外的换行符,那么双引号方法是可能的,但很麻烦。要弄清楚,向后工作:echo -e
转换\\
为\
和转换\n
为换行符,双引号转换\\
为\
,因此您可以使用六个反斜杠 (echo -e "Hello\\\\\\n"
) 来完成,因为一个\\n
反斜杠\n
转义另一个反斜杠。\n
您也可以使用五个来执行此操作,因为当\
未转义时,双引号将保留。这说明了单引号的好处:只需将您想
echo -e
看到的任何内容放在单引号 (echo -e 'Hello\\\n'
) 中。printf
这里也不错。一种选择是printf 'Hello\\\n\n'
。但printf
真正闪耀的是你可以插入额外的参数。您可以使用printf '%s\n\n' 'Hello\'
, 插入第二个参数(字面意思是Hello\
因为单引号不会改变任何东西)代替%s
.