为什么 dash 的 echo 扩展 \\\\ 与 bash 的 echo 不同?

csi*_*ac2 7 bash dash echo quoting

我有一个小的开源项目,出于各种原因,我试图用相当可移植的 shell 脚本编写。它的自动化集成测试检查路径表达式中的敌对字符是否得到正确处理,等等。

/bin/sh提供的用户bash在测试中看到失败,我已将其简化为以下内容:

echo "A bug\\'s life"
echo "A bug\\\\'s life"
Run Code Online (Sandbox Code Playgroud)

在 bash 上,它会产生以下预期结果:

A bug\'s life
A bug\\'s life
Run Code Online (Sandbox Code Playgroud)

使用我开发的破折号,它可以执行以下操作:

A bug\'s life
A bug\'s life
Run Code Online (Sandbox Code Playgroud)

我想我没有在 dash 中发现错误,我可能会遗漏一些东西。对此有合理的解释吗?

Sté*_*las 12

echo "A bug\\'s life"
Run Code Online (Sandbox Code Playgroud)

因为那些是双引号,并且\在双引号内是特殊的\,所以 shell将第一个理解为转义/引用第二个\. 所以一个A bug\'s life参数被传递给echo.

echo "A bug\'s life"
Run Code Online (Sandbox Code Playgroud)

会达到完全一样的。'在双引号内并不特殊,\不会被删除,因此它与传递给echo.

正如为什么 printf 比 echo 好?echo实现之间有很多变化。

在符合 UNIX 的实现中,如dash's echobuiltin¹,\用于引入转义序列:\n换行符、\b退格符、\0123八进制序列......以及\\反斜杠本身。

一些(非 POSIX)需要一个-e选项,或者仅在符合模式下执行(例如bash's 当使用正确的选项构建时,如shOS/X 或SHELLOPTS=xpg_echo在环境中调用时)。

所以在标准(仅限 Unix 标准;POSIX 未指定行为)中echo

echo '\\'
Run Code Online (Sandbox Code Playgroud)

与...一样:

echo "\\\\"
Run Code Online (Sandbox Code Playgroud)

输出一个反斜杠,而在bash不处于一致性模式时:

echo '\\'
Run Code Online (Sandbox Code Playgroud)

将输出两个反斜杠。

最好避免echo并使用它printf

$ printf '%s\n' "A bug\'s life"
A bug\'s life
Run Code Online (Sandbox Code Playgroud)

在所有printf实现中,在此实例中的工作原理相同。


¹ dash'secho在这方面是合规的,但在echo -nUNIX 规范 (POSIX + XSI) 要求它输出-n<newline>.