为什么echo“ bar” -n与echo -n“ bar”不同?


10

相比

echo -n "bar"

echo "bar" -n

前者做了认为应该做的事情(打印“ bar”而不换行),而后者则没有。这是错误还是设计使然?为什么它与许多cli程序的不同之处在于您无法移动选项?例如,tail -f /var/log/messages与完全相同tail /var/log/messages -f。当我忘记了我想要前者时,有时会做后者,因为在内部通常通过getopt重新排列选项和参数。

更新:是的,我最初讨厌我的问题。我删除了您必须查看历史才能使某些答案有意义的nerf。


3
从我所看到的,所不同的立即明显。echo -n "bar"给“ bar”,而echo "bar" -n给“ bar -n”
phunehehe 2011年

Answers:


18

正如大多数其他人所观察到的,如果将“ -n”放置在echo命令之后但紧随其后的位置,则将按字面意义进行解释。

从历史上看,UNIX实用程序都是这样的-它们仅在命令名称后立即寻找选项。可能是BSD或GNU率先提出了更灵活的样式(尽管我可能是错的),因为即使现在POSIX仍将旧方法指定为正确的方法(请参见指南9,也适用man 3 getopt于Linux系统)。无论如何,即使这些天大多数Linux实用程序都使用新样式,也存在一些类似的坚持echo

Echo从标准的角度来看,这是一个烂摊子,因为到POSIX出现时,至少有两个根本上相互冲突的版本在起作用。一方面,您具有SYSV样式,该样式可解释反斜杠转义的字符,但否则将按原样对待其参数,不接受任何选项。另一方面,您具有BSD样式,该样式将首字母-n作为特殊情况对待,并且从字面上绝对输出其他所有内容。既然如此echo方便,您就有成千上万个依赖于一种行为或另一种行为的shell脚本:

echo Usage: my_awesome_script '[-a]' '[-b]' '[-c]' '[-n]'
echo -a does a thing.
echo -b does something else.
echo -c makes sure -a works right.
echo -- DON\'T USE -n -- it\'s not finished! --

由于“按字面意义处理所有内容”的语义,即使不加echo破坏也无法添加新选项。如果GNU在上面使用了弹性选项方案,地狱就会崩溃。

顺便说一句,为了使Bourne Shell实现之间达到最佳兼容性,请使用printf而不是echo

更新以解释为什么echo特别不使用灵活选项。


赞成,因为您是唯一要提及的人,这是预期的getopt行为。
杰弗里·巴切莱特

@jander为什么回显是“保持”?我认为这是一个gnu coreutil?
xenoterracide

@xeno:我已经更新了答案。基本上,GNU不想破坏事情。
Jander)

1
在第一个非选项之后接受选项是特定于GNU实用程序和使用GNU libcgetopt工具的程序的。通过设置环境变量,用户始终可以获得向后兼容的行为POSIXLY_CORRECT
吉尔(Gilles)“所以,别再邪恶了”,

1
对于的特定情况echo,也有一些实现可以识别-e-E作为选项。为了便于携带,请勿以开头-或使用printf %s -e
吉尔(Gilles)“所以,别再邪恶了”,

9

其他答案可以使您了解手册页,从而发现-n成为要回显的字符串的一部分。但是,我只想指出,没有md5sum就能很容易地对此进行调查,并使所发生的事情变得更加隐晦。

[11:07:44][dasonk@Chloe:~]: echo -n "bar"
bar[11:07:48][dasonk@Chloe:~]: echo "bar" -n
bar -n

3
+1。如果管道没有达到您的期望,请分别测试每个部分。
Mikel

6

哇,每个人的解释都很冗长。

就这么简单:

-n 如果出现在字符串之前,则是一个选项,否则,它只是要回显的另一个字符串。

删除| md5sum ,您将看到输出有所不同。


5

从简单的检查来看,这并不是设计错误。

echo "bar" -n | md5sum

a3f8efa5dd10e90aee0963052e3650a1

自己尝试以下命令:

echo "bar -n" | md5sum

您会注意到生成的md5是

a3f8efa5dd10e90aee0963052e3650a1

您只是在回显中混合了-n的使用。

在您的第一个示例代码中

echo -n "bar" | md5sum

-n用于表示在此回显之后不要添加换行符。

您的第二个样本

echo "bar" -n | md5sum

将-n当作文字文本。

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.