shell中的“无效算术运算符”

时间:2013-08-15 10:30:22

标签: linux bash shell unix

cat test.sh

#!/bin/bash
key="index";
arr[$key]="val"
echo ${arr[${key}]}

/ bin / bash-x test.sh

+ key=index
+ arr[$key]=val
+ echo val
val

然后我修改了test.sh:

#!/bin/bash
key="index.index";
arr[$key]="val"
echo ${arr[${key}]}

/ bin / bash -x test.sh

+ key=index.index
+ arr[$key]=val
test.sh: line 3: index.index: syntax error: invalid arithmetic operator (error token is ".index")
test.sh: line 4: index.index: syntax error: invalid arithmetic operator (error token is ".index")

为什么出现此错误,任何建议都会受到欢迎!

3 个答案:

答案 0 :(得分:6)

此:

key="index";
arr[$key]="val"
echo ${arr[${key}]}

只有出现才能正常工作。由于arr是普通数组,而不是关联数组,因此只能用非负整数值编制索引。

考虑这个有效的代码:

index=42
key="index"
arr[$key]="val"
echo ${arr[42]}
echo ${arr[index]}
echo ${arr[$index]}
echo ${arr['index']}
echo ${arr["index"]}
echo ${arr[\index]}

所有echo语句都打印val。由于索引被视为算术表达式,因此它可以引用带有或不带$index前缀的变量(在本例中为$) - 即使它是带引号的字符串。

在代码中,您从未将值分配给$index${arr[${key}]}会扩展为${arr[index]},相当于${arr[$index]},会被视为(默认情况下)等同于${arr[0]}

(如果您有set -o nounset,则对未设置变量的引用将被视为错误,您的代码将生成错误消息。)

你的第二块代码:

key="index.index";
arr[$key]="val"
echo ${arr[${key}]}

无效,因为index.index不是有效的变量名称 - 即使您可能只是将其视为用作数组索引的字符串。

如果希望arr允许任意字符串作为索引,则它必须是关联数组。您可以通过分配非关联数组(或使用declare -a)来创建非关联数组,但只能使用declare -A创建关联数组。

在版本4中将关联数组添加到bash中。如果您使用的是早期版本的bash,则不支持declare -A。您需要升级到更新的bash,编写一些笨拙的替代品,或使用支持关联数组的语言,如Awk,Python或Perl。

添加declare -A arr(如user000001's answer建议的那样)应解决问题(如果你有bash 4),但了解原始代码实际在做什么(或者更确切地说没有做)是有益的。< / p>

(顺便说一下,谢谢你提出这个问题;我在撰写这个答案时学到了很多东西。)

答案 1 :(得分:5)

使用declare -A arr将数组变量声明为关联数组。

$ cat test.sh 
#!/bin/bash
set -x 
declare -A arr
key="index.index";
arr["$key"]="val"
echo "${arr["${key}"]}"

$ ./test.sh 
+ declare -A arr
+ key=index.index
+ arr["$key"]=val
+ echo val
val

答案 2 :(得分:1)

此行为因BASH版本而异。较旧的BASH版本仅允许非负整数作为数组中的键。

请注意,BASH中的变量名称不允许dot/period

有关BASH中允许的字符的更多详细信息,请参阅此问答:Allowed characters in linux environment variable names

修改

(非常感谢@chepner的这个附录)

常规数组(非关联数组)仅由整数索引。用作方括号之间索引的任何表达式都被视为算术表达式。 $ key扩展为index,然后将其视为(未设置)变量,扩展为0.如果为索引分配了值3,则为${array[$key]} -> ${array[index]} -> ${array[3]}。这是一种隐式间接参数扩展