为什么bash吞咽-e在阵列的前面

Sam*_*ron 9 bash

给出以下语法:

x=(-a 2);echo "${x[@]}";x=(-e 2 -e); echo "${x[@]}"
Run Code Online (Sandbox Code Playgroud)

输出:

-a 2
2 -e
Run Code Online (Sandbox Code Playgroud)

期望的输出

-a 2
-e 2 -e
Run Code Online (Sandbox Code Playgroud)

为什么会这样?我该如何解决?

Mic*_*pat 11

TL;博士

printf "%s\n" "${x[*]}"
Run Code Online (Sandbox Code Playgroud)

说明

echo 需要3个选项:

$ help echo
[…]
Options:
  -n    do not append a newline
  -e    enable interpretation of the following backslash escapes
  -E    explicitly suppress interpretation of backslash escapes
Run Code Online (Sandbox Code Playgroud)

所以,如果你运行:

$ echo -n
$ echo -n -e
$ echo -n -e -E
Run Code Online (Sandbox Code Playgroud)

你一无所获.即使你将每个选项都放在引号中,它仍然看起来与bash相同:

$ echo "-n"
$ echo "-n" "-e"
Run Code Online (Sandbox Code Playgroud)

最后一个命令运行echo两个参数:-n-e.现在将其与:

$ echo "-n -e"
-n -e
Run Code Online (Sandbox Code Playgroud)

我们所做的是echo一个参数运行:-n -e.由于bash不识别(组合)选项-n -e,它最终会像我们想要的那样回应终端的单个参数.

适用于阵列

在第二种情况下,数组x以元素开头-e.在bash扩展数组后${x[@]},您正在有效地运行:

$ echo "-e" "2" "-e"
2 -e
Run Code Online (Sandbox Code Playgroud)

由于第一个参数是-e,它被解释为一个选项(而不是回显到终端),正如我们已经看到的那样.

现在将其与其他样式的数组扩展进行对比${x[*]},它有效地执行以下操作:

$ echo "-e 2 -e"
-e 2 -e
Run Code Online (Sandbox Code Playgroud)

bash看到了单个参数-e 2 -e- 因为它不认识到这是一个选项 - 它会将参数回显给终端.

请注意,${x[*]}样式扩展通常不安全.请看以下示例:

$ x=(-e)
$ echo "${x[*]}"
Run Code Online (Sandbox Code Playgroud)

即使我们希望-e得到回应,也没有任何印刷品.如果你一直在关注,你已经知道为什么会这样.

逃离

解决方案是转义echo命令的任何参数.不幸的是,与其他提供某种说法的命令不同,"嘿!以下参数不应被解释为选项 "(通常是--参数),bash不提供这样的转义机制echo.

幸运的是,有一个printf命令,它提供了所echo提供功能的超集.因此我们得出了解决方案:

printf "%s\n" "${x[*]}"
Run Code Online (Sandbox Code Playgroud)