哪里在bash递归变量扩展/壳数字背景从何而来? [英] Where does the recursive variable expansion in bash/shell numeric contexts come from?
问题描述
使用方面的POSIX规范各国算术展开了
The POSIX spec states with regard to Arithmetic Expansion that
[我] F中的shell变量x包含形成一个有效的整型常量,可选择其中一个领先的加号或减号,那么算术扩展的值$((X))和$(($ X) )应返回相同的值。
[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.
这是一个合理的快捷方式,相当不错清理复杂的前pressions。
Which is a reasonable shortcut and cleans up complicated expressions rather nicely.
庆典(版本 3.2.25(1)-release
从CentOS的5和 33年3月4日(1)-release
与debian不稳定),以及KSH(版本AJM93吨+ 2010-06-21
从CentOS的5)似乎都向前迈进一步那么这不过。
bash (versions 3.2.25(1)-release
from CentOS 5 and 4.3.33(1)-release
from debian unstable) as well as ksh (Version AJM 93t+ 2010-06-21
from CentOS 5) all seem to go one step farther then that however.
他们似乎都递归扩展算术扩展中遇到的变量(和数字环境中的 [
使用该数值运算的结果)。
They all seem to recursively expand variables encountered in arithmetic expansion (and numeric contexts in [[
resulting from using the numeric operators).
具体做法是:
$ 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
来自哪儿呢这种行为,为什么它会永远是可取的?
Where does this behavior come from and why would it ever be desirable?
这使得使用 [
在 [
明确 安全使用时少与数字运算符,因为无效的价值观和印刷错误被脚本错误被默默地有效(但可能错误)的测试去了。
It makes using [[
in place of [
explicitly less safe when used with numeric operators because invalid values and typographical errors go from being script errors to being silently valid (but likely erroneous) tests.
编辑:作为一个方面的问题,如果有人碰巧知道的在的这一特性被加入到庆典的/ etc。我有兴趣知道这一点。
As a side question if anyone happens to know when this "feature" was added to bash/etc. I would be interested in knowing that as well.
推荐答案
这是比你想象的更糟糕。该变量的值被递归地视为一个算术前pression:
It's worse than you think. The value of the variable is recursively treated as an arithmetic expression:
$ foo='bar+bar'
$ echo $((foo))
10
的变量的值作为运算前pression评价时,它被引用时,或者当已在实施利用声明-i'的整数属性的变量被分配一个值。
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.
后半部分意味着你可以这样做:
The latter part means you can do:
$ declare -i int
$ int=bar+bar
$ echo $int
10
请注意,这一切都不是违反你上面引述的规范。它只是说,如果变量的值是一个整型常量应该做什么。这并不是说,如果该值是另一回事,这让那个打开的实现添加这样的扩展应该怎样做。 击黑客维基解释它:
如果该变量不成立,看起来像一个有效的前pression(数字或操作)的值,前pression被重新用来参考,例如命名参数
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
如果最终的扩张不是有效的前pression,你会得到一个错误:
If the eventual expansion is not a valid expression, you'll get an error:
$ foo='a b'
$ bar=foo
echo $((bar))
bash: a b: syntax error in expression (error token is "b")
所以,如果您的变量包含随机的东西,它可能会导致错误。但如果只包含一个字,这是有效的变量语法,如果变量没有设置,将评估为 0
。
这篇关于哪里在bash递归变量扩展/壳数字背景从何而来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!