【问题标题】:"invalid arithmetic operator" in shellshell中的“无效算术运算符”
【发布时间】:2013-08-17 12:49:39
【问题描述】:

猫测试.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")

为什么会出现这个错误,任何建议都将不胜感激!

【问题讨论】:

    标签: linux bash shell unix


    【解决方案1】:

    这个:

    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 创建关联数组。

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

    添加declare -A arr(正如user000001's answer 所建议的那样)应该可以解决问题(如果您有 bash 4),但是了解您的原始代码实际上在做什么(或者说不做什么)是有益的。

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

    【讨论】:

      【解决方案2】:

      使用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
      

      【讨论】:

      • 值得注意的是,之前,字符串“index”在用作索引时被视为未设置的变量,因此被评估为0。
      【解决方案3】:

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

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

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

      编辑:

      (非常感谢@chepner 提供此附录)

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

      【讨论】:

      • 这也适用于关联数组吗?因为当你 declare -A 数组时它似乎可以工作。
      • GNU bash, version 4.1.2 对我不起作用。你有哪个 BASH 版本?
      • 我有GNU bash, version 4.2.25(1)-release (i686-pc-linux-gnu)。奇怪
      • 常规数组(非关联数组)仅按整数索引。任何用作方括号之间索引的表达式都被视为算术表达式。 $key 扩展为 index,然后将其视为扩展为 0 的(未设置)变量。如果您为 index 分配了一个值,例如 3,则为 ${array[$key]} -> ${array[index]} -> ${array[3]}。这是一种隐式间接参数扩展。
      • 你是对的;关联数组在版本 4 中被添加到 bash。但是数组的键/索引中的 . 字符仍然没有什么特别之处。变量名必须是标识符,这意味着它们不能包含.。普通数组的索引必须是非负整数; . 没有什么特别之处,它们不能包含除 _ 之外的任何标点符号。关联数组的索引(仅存在于 bash 4 和更高版本中)可以是任意字符串;同样,. 并没有什么特别之处。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-17
      • 2019-04-16
      • 2019-12-16
      • 2011-03-02
      • 2020-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多