当我的脚本以不同的方式启动时,为什么echo -n“...”的结果会有所不同?

时间:2016-09-27 22:39:24

标签: shell

我有

$>echo -n "\033[40m  "

如果我在命令行上唤起它,将其保存到文件并在命令行上唤起文件,结果会有所不同。

我在mac上使用zsh,但希望这也适用于bash。输出不应该完全一样吗?如果没有,为什么?

1 个答案:

答案 0 :(得分:4)

echo -n的行为在shell之间是不同的(并且zsh和bash确实是不同的shell),因为它确实是未定义的行为:The POSIX sh specification不需要shell以任何特定的方式运行处理时:

  

应支持以下操作数:

     

string - 要写入标准输出的字符串。如果第一个操作数是-n,或者如果任何操作数包含反斜杠(\)字符,则结果是实现定义的。

使用XSI扩展时,echo需要处理反斜杠转义序列,如\033,不再给出进一步的参数;没有这些扩展,根本不需要处理这些序列,而是纯粹是实现定义的行为(因此取决于您的特定shell)。

作为明确定义的替代方案,请考虑:

#!/bin/sh
#      ^^ - because this code doesn't use any shell-specific extensions;
#           use #!/bin/zsh if zsh-only, #!/bin/bash if bash-only, etc.

printf '%b' "\033[40m  "

上述行为相同,无论是使用. yourscript./yourscriptbash yourscriptsh yourscript还是zsh yourscript调用,因为它完全由POSIX规范(并且不依赖于zsh选择破坏该规范的任何行为)。

如果您使用的是特定于shell的扩展,则需要使用./yourscript调用(以便根据其内容选择shell来表示第一行),并使用. yourscript仅使用相同的shell,或使用<shellname> yourscript再次使用特定的shell。

出于这个原因,./yourscript用法是首选,因为它允许脚本本身控制自己的解释器。

再次从POSIX echo规范中引用,这次来自“应用程序使用”部分:

  

除非-n(作为第一个参数)和转义序列都被省略,否则不可能在所有POSIX系统中使用echo。

     

printf实用程序可以移植来模拟echo实用程序的任何传统行为,如下所示(假设IFS具有其标准值或未设置):

     

此系列IEEE Std 1003.1-2001中历史性的System V回声和对XSI实现的要求等同于:

printf "%b\n" "$*"
     

BSD回声相当于:

if [ "X$1" = "X-n" ]
then
    shift
    printf "%s" "$*"
else
    printf "%s\n" "$*"
fi
     

鼓励新应用使用printf代替echo