比较
echo -n "bar"
和
echo "bar" -n
前者做什么我认为它应该这样做(打印“bar”而不换行),而后者则没有。这是一个错误还是设计使然?为什么它与许多 cli 程序不同,不能移动选项?例如,tail -f /var/log/messages
与 完全相同tail /var/log/messages -f
。当我忘记我想要前者时,有时我会做后者,因为在内部选项和参数通常会被重新排列获取选择。
更新:是的,我最初削弱了我的问题。我删除了你必须查看历史记录才能使某些答案有意义的削弱。
答案1
正如大多数其他人所观察到的,如果将“-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
特别不使用灵活选项。
答案2
其他答案都直指这一点,您可以查看手册页以了解 -n 正在成为要回显的字符串的一部分。不过,我只想指出,无需 md5sum 即可轻松调查此问题,并使发生的事情不那么神秘。
[11:07:44][dasonk@Chloe:~]: echo -n "bar"
bar[11:07:48][dasonk@Chloe:~]: echo "bar" -n
bar -n
答案3
哇,大家的解释都很长。
就这么简单:
-n
如果它出现在字符串之前,则它是一个选项,否则它只是另一个要回显的字符串。
删除它| md5sum
,您会看到输出有所不同。
答案4
从简单的检查来看,这不是设计上的错误......
echo "bar" -n | md5sum
a3f8efa5dd10e90aee0963052e3650a1
亲自尝试一下这个命令:
echo "bar -n" | md5sum
您会注意到生成的 md5 是
a3f8efa5dd10e90aee0963052e3650a1
您只是在 echo 中混淆了 -n 的使用。
在您的第一个示例代码中
echo -n "bar" | md5sum
-n 用于表示不要在此回显之后添加换行符。
您的第二个样本
echo "bar" -n | md5sum
将 -n 视为文字文本。