Bash:算术扩展、参数扩展和逗号运算符

Bash:算术扩展、参数扩展和逗号运算符

我有一个关于 bash 的参数扩展的问题,在逗号表达式内,在算术表达式内。我有两个我认为应该是等价的陈述,但它们不是。

为什么 bash 行

n=3; k=10; echo $((n++,k=$n))

输出3而不是4? (如我所料,它设置n为,但设置为。)4k3

相反,bash 行

 n=3; k=10; echo $((n++,k=n))

输出4,正如我所料。 (它设置n4,并且也k设置为4。)

我尝试在两个 bash 行中替换n++with ++n、 withn=n+1和 with n=$((n+1)),它们都会产生相同的差异:在所有脚本中k=$n产生,在所有脚本中产生。3k=n4


我的理解是,如果 的值n是一个整数(它确实是),$n并且n在算术表达式中应该具有相同的值。 (由于其(( ... ))构造,这是一个算术表达式。)根据 bash 手册,在算术求值部分中,在算术表达式中:

   Shell variables are allowed as  operands;  parameter  expansion  is  performed  before  the
   expression  is  evaluated.  Within an expression, shell variables may also be referenced by
   name without using the parameter expansion syntax.

那么为什么 bash 的处理方式$n与本例中不同n,它到底是如何评估的呢$n


如果不使用逗号运算符,我无法重复该问题。据我所知,逗号运算符从左到右计算其每个组件子表达式,包括计算每个组件时该组件的所有副作用。逗号表达式的值就是最后计算的分量(最右边的)的值。


这个问题是在一个更复杂的脚本的背景下出现的,我最终将其范围缩小到这个简单的示例来演示该问题。

那么,我对算术扩展、参数扩展或逗号运算符有什么误解?

请注意,我并不是在寻找解决方法,因为我已经有了一个解决方法: with 的版本n$n我的预期工作。我只是想了解 bash 在带有 的版本中做了什么$n,以及为什么它与仅带有 的版本做了不同的事情n

答案1

发生 shell 参数扩展在计算表达式之前,包括逗号处理

该表达式被视为位于双引号内,但括号内的双引号不会被特殊处理。表达式中的所有标记都会经历参数和变量扩展、命令替换和引号删除。结果被视为要计算的算术表达式。

你可以看到这个

unset n
echo $((n++,k=$n))

错误消息,

bash: n++,k=: syntax error: operand expected (error token is "=")

显示$n在处理整个算术表达式之前被替换。

在您的情况下,计算的表达式是

n++,k=3

答案2

在 内部$((...)),首先进行扩展,就像使用双引号一样,然后评估结果。

因此,在n=3; k=10; echo $((n++,k=$n))(or n=1; echo "$((++n + $n))",不限于,) 中,计算的算术表达式为n++, k=3

在这里,您需要:

n=3; k=10; echo "$((n++,k=n))"

(另请注意引号,因为算术扩展与 POSIX shell 中其他形式的单词扩展一样受 split+glob 的约束)。


1,您会发现调用数组和关联数组的一些变化,因为某些 shell 会在包含$((hash[$key]++))时尝试正确处理$key]

相关内容