Joh*_*024 35

echo -e并且echo $'...'两者的相似之处在于它们支持以下转义序列:

  \a     alert (bell)
  \b     backspace
  \e
  \E     an escape character
  \f     form feed
  \n     new line
  \r     carriage return
  \t     horizontal tab
  \v     vertical tab
  \\     backslash
  \0nnn  the eight-bit character whose value is the octal value nnn (zero to three octal digits)
  \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
  \uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
  \UHHHHHHHH
         the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)
Run Code Online (Sandbox Code Playgroud)

他们确实有区别。除上述之外,还echo -e支持:

  \c     suppress further output
  \0nnn  the eight-bit character whose value is the octal value nnn (zero to three octal digits)
Run Code Online (Sandbox Code Playgroud)

相比之下,$'....'支持:

 \'     single quote
 \"     double quote
 \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
 \cx    a control-x character
Run Code Online (Sandbox Code Playgroud)

请注意,在两者之间,\c扩展名是不兼容的:

$ echo -e  'start\n\cIstop'
start
$ echo  $'start\n\cIstop'
start
        stop
Run Code Online (Sandbox Code Playgroud)

对于echo -e上述,\c抑制进一步的输出,从而忽略Istop. 相比之下,对于$'...'\cI被解释为选项卡。

视觉上相似的形式: $"..."

相比之下$'...', 的功能$"..."就大不相同了。它将导致它包含的字符串根据当前语言环境进行翻译。

echo -e争议

echo -e壳并不普遍支持,许多人认为该-e选项是设计错误。观察:

$ ls
-e  -n
$ echo *
$ printf "%s\n" *
-e
-n
Run Code Online (Sandbox Code Playgroud)

如您所见,如果您要打印的内容以echo破折号开头,则结果可能出乎意料。除非您确定要打印的第一个字符串echo不以破折号开头,否则最好使用printf.

由于这些原因,POSIX 标准得出结论

鼓励新应用程序使用 printf 而不是 echo。

bash过去 22 年一直坚持的 Chet Ramey同意

[N] 新代码应该使用 printf。

  • 来自 globs 的意外选项(如 `*`)的问题实际上并不是 `echo` 特有的。任何识别短选项或长选项(以传统方式编写)并采用文件名操作数的命令都会发生这种情况,[包括`ls`](http://paste.ubuntu.com/8578017/)。可以说,`echo` 的情况有点糟糕,因为(正如你的消息来源提到的)`echo` 通常不接受 `--` 来表示选项的结束,而可以编写像 `ls -- *l` 这样的命令. (实际上,当使用以 `*` 或 `-` 开头的 glob 时,通常应该这样编写命令,尤其是在脚本中。) (2认同)