超出表达式递归级别

use*_*598 4 bash arithmetic-expressions

不知道为什么以下示例中存在错误:

$ a=1; (( a > 0 )) && echo y || echo n
y
$ a=x; (( a > 0 )) && echo y || echo n
n
$ a=a; (( a > 0 )) && echo y || echo n
-bash: ((: a: expression recursion level exceeded (error token is "a")
n
Run Code Online (Sandbox Code Playgroud)

koj*_*iro 7

$ a=a
( no error )
$ declare -i a
$ a=a
-bash: ((: a: expression recursion level exceeded (error token is "a")
Run Code Online (Sandbox Code Playgroud)

这种行为是因为declare -i将赋值的RHS放在算术上下文中.在算术上下文中,bash以递归方式将变量名称解引用到它们的值.如果名称取消引用自身,则会发生无限递归.

为了进一步说明,如果在该名称上设置整数属性之前将有问题的变量分配给与变量名称相同的字符串,则只会出现此行为.

$ unset a
$ declare -i a
$ a=a
( This is fine, $a dereferences to 0. )
$ unset a
$ a=a
$ declare -i a
$ a=a
-bash: ((: a: expression recursion level exceeded (error token is "a")
Run Code Online (Sandbox Code Playgroud)

这就是为什么这种情况很少发生的原因.如果在已经处于算术上下文中时执行赋值,则右侧无法解析为整数之外的任何内容.不会发生递归.所以要么

  1. 做好一切(( )).(你也可以在那里做作业.)
  2. 使用declare -i第一件事; 不要混合类型.


Bar*_*mar 5

在算术表达式中使用变量但值不是数字时,shell会将其视为要评估的另一个表达式.因此,如果值是变量名,它将获取该变量的值并使用它.但在这种情况下,你有它指向自己.所以要评估a它必须进行评估a,并且不断重复.