简体   繁体   English

重击:引用数组扩展导致奇怪的结果

[英]Bash: quoted array expansion leads to strange results

While experimenting with bash arrays, I stumbled upon behaviour I find hard to explain. 在尝试bash数组时,我偶然发现了难以解释的行为。

> arr=("a" "b")
> bash -c "echo ${arr[*]}"
a b
> bash -c "echo ${arr[@]}"
a

The relevant part of the bash manual states: bash手册的相关部分指出:

${!name[@]}, ${!name[*]} : If name is an array variable, expands to the list of array indices (keys) assigned in name. $ {!name [@]},$ {!name [*]}:如果name是一个数组变量,则扩展到name中分配的数组索引(键)列表。 [...] When '@' is used and the expansion appears within double quotes, each key expands to a separate word. [...]当使用“ @”并且扩展名出现在双引号中时,每个键都会扩展为一个单独的单词。

As I understand it, I would expect the latter example to expand from bash -c "echo ${arr[@]}" to bash -c "echo \\"a\\" \\"b\\"" (or even bash -c "echo ab" ) and output ab in the subshell. 据我了解,我希望后一个示例从bash -c "echo ${arr[@]}"扩展到bash -c "echo \\"a\\" \\"b\\"" (甚至bash -c "echo ab" )并在子外壳中输出ab

So, which is the correct behaviour? 那么,哪个是正确的行为? The observed behaviour? 观察到的行为? The behaviour I expect? 我期望的行为? Or something entirely different? 还是完全不同的东西?

You can run the code under set -xv to see how bash expands the variables: 您可以在set -xv下运行代码,以查看bash如何扩展变量:

choroba@triangle:~ $ (set -xv ; arr=("a" "b") ; bash -c "echo ${arr[@]}")
+ arr=("a" "b")
+ bash -c 'echo a' b
a

"echo ${arr[@]}" is expanded to two words, echo a and b , the first one is used as a command to run, the second one is interpreted as the value for the $0 or name of the shell. "echo ${arr[@]}"扩展为两个单词, echo ab ,第一个用作运行命令,第二个解释为$0的值或外壳名称。 Any following arguments would be used to set the positional parameters. 以下任何自变量都将用于设置位置参数。

"echo ${arr[@]}" expands to two words, echo a , and b . "echo ${arr[@]}"扩展为两个单词, echo ab And the manual also says 手册还说

If the -c option is present, then commands are read from the first non-option argument command_string. 如果存在-c选项,那么将从第一个非选项参数command_string中读取命令。 If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters. 如果在command_string之后有参数,则第一个参数分配给$ 0 ,其余所有参数分配给位置参数。 The assignment to $0 sets the name of the shell, which is used in warning and error messages. $ 0的赋值设置外壳的名称,该名称用于警告和错误消息。

So, you're assigning b to $0 there. 因此,您将b分配给$0

Proof of concept: 概念证明:

$ arr=(a b)
$ bash -c "echo \$0; echo ${arr[@]}"
b
a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM