Bash和Dash对使用命令`echo -ne "hello\n"`的行为差异

7

使用相同的命令 echo -ne "hello\n" 在bash和dash中会有不同的行为。具体如下:

$ bash -c 'echo -ne "hello\n"'
hello
$ dash -c 'echo -ne "hello\n"'
-ne hello

为什么会这样?我完全不理解...
我的系统:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.5 LTS
Release:    12.04
Codename:   precise

1
破折号在符合 POSIX 标准的情况下正确地遵循 echo 应该如何行事;Bash 忽略了该标准(这是极少数情况之一,不是扩展未定义的行为,而是完全不兼容)。 - Charles Duffy
顺便提一下,如果你export POSIXLY_CORRECT=1,然后使用GNU的/bin/echo,你会看到它的行为方式是相同的。 - Charles Duffy
@CharlesDuffy: bash 没有忽略,它只是默认没有选择那种行为。 - cuonglm
@cuonglm,说得好。即便如此,我仍然认为Chet在选择默认情况下不符合规范的行为方面犯了严重错误(尽管现在肯定为时已晚)。 - Charles Duffy
3个回答

11

POSIX规范中的echo命令不支持任何参数。您可以在此查看该规范。

虽然规范提到了-n,但是它是为了说明它既不是选项,而且可能是实现定义的情况或被视为字符串。

所以dash正是这样做的。

另一方面, bash在许多方面都有不符合规范的行为。

这就是为什么通常不建议使用echo,而是使用printf,它具有更好的规范和更好的可移植性行为。


дҪ еҸҜд»ҘдҪҝbashзҡ„echoз¬ҰеҗҲ规иҢғпјҢеҸӮи§ҒжҲ‘зҡ„еӣһзӯ”гҖӮ - cuonglm
这是否意味着 echo 不是一个程序,而是 shell 的本地命令? - Quentin
1
@Quentin:你的shell中经常有echo内置命令,还有外部程序/bin/echo - cuonglm
1
@Quentin,如果使用外部的/bin/echo程序,您不会看到它根据活动shell更改行为。几十年来,没有包括echo作为内置命令的shell几乎是闻所未闻的。 - Charles Duffy
好的,这真的很有道理,我原以为它是一个外部程序,所以我无法理解为什么在不同的shell中行为会有所不同。 - Quentin

2

虽然 bash 中的 echo 实现默认情况下不符合 POSIX 和 Unix 标准,但是你可以在运行时或编译时更改其行为。

在运行时,通过使用 xpg_echo 以及进入 POSIX 模式,bashecho 就符合标准了:

$ env BASHOPTS=xpg_echo SHELLOPTS=posix bash -c 'echo -ne "hello\n"'
-ne hello

或者:

$ env BASHOPTS=xpg_echo POSIXLY_CORRECT= bash -c 'echo -ne "hello\n"'
-ne hello

在编译时,您可以向configure脚本传递--enable-xpg-echo-default--enable-strict-posix-default选项。


0
在之前的回答中提到,dash不使用/理解echo的-n参数,但这是不正确的。
Dash使用-n参数来不打印换行符。但是示例中使用了-ne。 以下内容均来自Debian中的dash版本0.5.12-2:
$ echo -n string
string$
$ echo -n -e string
-e string$
$ echo -ne string
-ne string
$

如你所见:
在 "echo -n string" 中,它打印出不带换行符的字符串。
在 "echo -n -e string" 中,它不打印换行符是因为 -n 是 dash 可识别的允许参数,然后它将 -e 视为字符串,因为根据 POSIX,它不是有效的参数。
在 "echo -ne string" 中,它将 -ne 视为字符串,因为根据 POSIX,它不是有效的参数(因为有 "e" 部分)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接