我有一个关于 bash 的参数扩展的问题,在逗号表达式内,在算术表达式内。我有两个我认为应该是等价的陈述,但它们不是。
为什么 bash 行
n=3; k=10; echo $((n++,k=$n))
输出3
而不是4
? (如我所料,它设置n
为,但设置为。)4
k
3
相反,bash 行
n=3; k=10; echo $((n++,k=n))
输出4
,正如我所料。 (它设置n
为4
,并且也k
设置为4
。)
我尝试在两个 bash 行中替换n++
with ++n
、 withn=n+1
和 with n=$((n+1))
,它们都会产生相同的差异:在所有脚本中k=$n
产生,在所有脚本中产生。3
k=n
4
我的理解是,如果 的值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
]