在 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
答案1
反斜杠被特殊处理echo -e
,但首先它们是有时由 shell 特殊处理(在本例中为bash
),根据 shell 的引用規則。
echo
其实看到的论点是Hello\\n
。因为您已将 传递-e
给echo
,所以它会对反斜杠转义进行特殊处理,并将\\
其折叠为单个\
。最后一个n
未转义,因此它按字面意思显示。
原因是,在echo
shell 自身运行之前,并且独立于其自身运行之外,\
特别对待在某些情况下,但在其他情况下则不然。未加引号的\
字符始终被特殊处理,单引号 \
从未得到特殊对待,但双引号 \
字符,就像您所运行的命令一样,更加微妙和复杂。
当 shell 在命令中遇到双引号文本时,例如,如果该文本位于双引号内本身具有特殊含义的字符之前,则"Hello\\\n"
它会将其视为转义字符\
而不是其他方式。
- 因为
\
sometimes 在 内部具有特殊含义""
,所以\
紧接在另一个 之前的\
具有引用第二个 的效果\
。因此在双引号内,第一个\\
被折叠为\
。 - 在前两个
\
字符之后,还有第三个\
字符,它不受前两个字符的影响,并且位于 之前n
。但是,n
它不是在双引号内被特殊处理的字符,因此,\
在这种情况下,它之前的 不会被特殊处理。因此,\n
仍然是\n
。
效果是,在双引号中,\\\n
被解释为\\n
。
当echo -e
看到时\\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
。