关于 Arithmetic Expansion 的 POSIX 规范说明那个
[i]f the shell variable x contains a value that forms a valid integer constant, optionally including a leading plus or minus sign, then the arithmetic expansions "$((x))" and "$(($x))" shall return the same value.
这是一个合理的快捷方式,可以很好地清理复杂的表达式。
bash(版本 3.2.25(1)-release
来自 CentOS 5 和 4.3.33(1)-release
来自 debian unstable)以及 ksh(版本 AJM 93t+ 2010-06-21
来自 CentOS 5) 然而似乎都比那更进一步。
它们似乎都递归地扩展在算术扩展中遇到的变量(以及 [[
中使用数字运算符产生的数字上下文)。
具体来说:
$ set -x
$ bar=5
+ bar=5
$ foo=bar
+ foo=bar
$ [ foo -gt 4 ]; echo $?
+ '[' foo -gt 4 ']'
-bash: [: foo: integer expression expected
+ echo 2
2
$ [[ foo -gt 4 ]]; echo $?
+ [[ foo -gt 4 ]]
+ echo 0
0
$ [[ foo -eq 0 ]]; echo $?
+ [[ foo -eq 0 ]]
+ echo 1
1
$ [[ foo -eq 5 ]]; echo $?
+ [[ foo -eq 5 ]]
+ echo 0
0
$ (( foo == bar )); echo $?
+ (( foo == bar ))
+ echo 0
0
$ (( foo == 1 )); echo $?
+ (( foo == 1 ))
+ echo 1
1
这种行为从何而来,为什么会令人满意?
当与数字运算符一起使用时,它使得使用 [[
代替 [
显式不太安全,因为无效值和打印错误从脚本错误到静默有效(但可能是错误的)测试。
编辑:作为附带问题,是否有人碰巧知道何时此“功能”被添加到 bash/etc。我也有兴趣知道这一点。
最佳答案
这比你想象的更糟。变量的值被递归地视为一个算术表达式:
$ foo='bar+bar'
$ echo $((foo))
10
关于 Shell Arithmetic 的 bash 手册部分说:
The value of a variable is evaluated as an arithmetic expression when it is referenced, or when a variable which has been given the integer attribute using ‘declare -i’ is assigned a value.
后半部分意味着你可以这样做:
$ declare -i int
$ int=bar+bar
$ echo $int
10
请注意,所有这些都不违反您在上面引用的规范。它只说明如果变量的值是整数常量应该做什么。它没有说明如果值是其他值应该做什么,这使得实现可以添加这样的扩展。 Bash Hackers Wiki解释一下:
If the variable doesn't hold a value that looks like a valid expression (numbers or operations), the expression is re-used to reference, for example, the named parameters
如果最终的展开不是一个有效的表达式,你会得到一个错误:
$ foo='a b'
$ bar=foo
echo $((bar))
bash: a b: syntax error in expression (error token is "b")
因此,如果您的变量包含随机内容,则很可能会导致错误。但如果它只包含一个单词,这是有效的变量语法,那么如果未设置变量,它将计算为 0
。
关于bash - bash/shell 数字上下文中的递归变量扩展从何而来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29980940/