双括号结构在 bash 中如何工作?
How does the double parenthesis construct work in bash?
我读到 here 双括号允许 C 风格的变量操作。但是,当我尝试比较字符串时,它没有按预期工作:
(( "a" == "b" )) && echo yes || echo no
# shows yes
我也对 this 如何将变量用作布尔值感到困惑。按照链接答案中的示例,我尝试了以下操作:
true=1
false=0
a=true
(( a )) && echo yes || echo no
# shows yes
a=false
(( a )) && echo yes || echo no
# shows no
但是 a
不是 true 或 false 的字符串值吗?
此外,由于在 bash 中“无错误”值 (0) 被视为真而任何“错误”值(非零)被视为假,为什么它看起来像这里采用相反的约定?
要注意的主要事情是 double-parenthesis 构造允许 算术计算和扩展 ,而不是内联 C 解释器。因此,只有Shell Arithmetic中定义的规则适用,也就是说,只有整数类型的C运算在双括号中起作用。
第一个例子:bash构造先展开
首先根据 bash 规则扩展算术运算符之外的任何内容,例如quotes, parameter expansion、bash range {1..5}
和 list{a,b}
构造,在双括号计算开始之前。
在第一个例子中,双引号导致里面的内容被解释为一个单词(在 double-paren 中没有影响)并且还计算以 $ 开头的东西(但是引号中有 none ), 所以第一个例子简单地变成 (( a == b ))
.
因此,了解 (( ))
工作原理的最佳方法是首先在脑海中计算出所有 bash 结构,然后将其插入。您还可以编写示例来测试您的假设.
发生参数扩展的示例:
a=1
b=2
(( a = $b )) # becomes (( a = 2 ))
(( a = b )) # straight arithmetic evaluation of a = b within the double parenthesis
# they produce the same result but how they arrive at the result is different
(( $a = b )) # becomes (( 2 = b ))
# syntax error as that's not a valid expression.
备注
当您比较密切相关的 $(( ))
和 (( ))
结构时,有一些特殊之处。前者 (Arithmetic Expansion) 将表达式视为表达式在双引号内,而后者则不然,如上所述。
例子二:右值位置的变量递归展开
Shell Arithmetic中有一些微妙的规则:
- “变量的值在被引用时作为算术表达式求值”
- “或者当使用
declare -i
赋予整数属性的变量被赋值时”。
- “在不使用参数扩展语法的情况下按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0”
稍微尝试一下后,您会发现这基本上意味着右值中的任何变量都将被递归计算,直到它达到一个整数值,或者是一个 undefined/null 变量姓名:
b=c
c=d
(( a = b ))
echo $a
# gives 0
d=3
(( a = b ))
echo $a
# gives 3
unset d
declare -i a
a=b
echo $a
# gives 0
d=3
a=b
echo $a
# gives 3
您还可以玩把戏,将表达式放入变量中,然后再对其求值:
b=2
c=3
d=c
e=b+d
(( a = e ))
echo $a
# gives 5, as it unfolds like a=b+d; a=2+c; a=2+3
因此在问题的示例中,a
评估为 true
,然后评估为 1 以给出最终结果。
(( ))
如何颠倒真假的解释
(( 0 ))
echo $? # print the return code of the previous call
# prints 1, which indicates error/false in shell
(( 1 ))
echo $?
# prints 0, indicating success/true
(( 2 ))
echo $?
# prints 0
(( -1 ))
echo $?
# prints 0
所以括号内的行为与C对true和false的解释是一致的,0表示false,non-zero表示true。 (( ))
将 false“转换”为 return 值 1,将 true 转换为 return 值 0。
我读到 here 双括号允许 C 风格的变量操作。但是,当我尝试比较字符串时,它没有按预期工作:
(( "a" == "b" )) && echo yes || echo no
# shows yes
我也对 this 如何将变量用作布尔值感到困惑。按照链接答案中的示例,我尝试了以下操作:
true=1
false=0
a=true
(( a )) && echo yes || echo no
# shows yes
a=false
(( a )) && echo yes || echo no
# shows no
但是 a
不是 true 或 false 的字符串值吗?
此外,由于在 bash 中“无错误”值 (0) 被视为真而任何“错误”值(非零)被视为假,为什么它看起来像这里采用相反的约定?
要注意的主要事情是 double-parenthesis 构造允许 算术计算和扩展 ,而不是内联 C 解释器。因此,只有Shell Arithmetic中定义的规则适用,也就是说,只有整数类型的C运算在双括号中起作用。
第一个例子:bash构造先展开
首先根据 bash 规则扩展算术运算符之外的任何内容,例如quotes, parameter expansion、bash range {1..5}
和 list{a,b}
构造,在双括号计算开始之前。
在第一个例子中,双引号导致里面的内容被解释为一个单词(在 double-paren 中没有影响)并且还计算以 $ 开头的东西(但是引号中有 none ), 所以第一个例子简单地变成 (( a == b ))
.
因此,了解 (( ))
工作原理的最佳方法是首先在脑海中计算出所有 bash 结构,然后将其插入。您还可以编写示例来测试您的假设.
发生参数扩展的示例:
a=1
b=2
(( a = $b )) # becomes (( a = 2 ))
(( a = b )) # straight arithmetic evaluation of a = b within the double parenthesis
# they produce the same result but how they arrive at the result is different
(( $a = b )) # becomes (( 2 = b ))
# syntax error as that's not a valid expression.
备注
当您比较密切相关的 $(( ))
和 (( ))
结构时,有一些特殊之处。前者 (Arithmetic Expansion) 将表达式视为表达式在双引号内,而后者则不然,如上所述。
例子二:右值位置的变量递归展开
Shell Arithmetic中有一些微妙的规则:
- “变量的值在被引用时作为算术表达式求值”
- “或者当使用
declare -i
赋予整数属性的变量被赋值时”。 - “在不使用参数扩展语法的情况下按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0”
稍微尝试一下后,您会发现这基本上意味着右值中的任何变量都将被递归计算,直到它达到一个整数值,或者是一个 undefined/null 变量姓名:
b=c
c=d
(( a = b ))
echo $a
# gives 0
d=3
(( a = b ))
echo $a
# gives 3
unset d
declare -i a
a=b
echo $a
# gives 0
d=3
a=b
echo $a
# gives 3
您还可以玩把戏,将表达式放入变量中,然后再对其求值:
b=2
c=3
d=c
e=b+d
(( a = e ))
echo $a
# gives 5, as it unfolds like a=b+d; a=2+c; a=2+3
因此在问题的示例中,a
评估为 true
,然后评估为 1 以给出最终结果。
(( ))
如何颠倒真假的解释
(( 0 ))
echo $? # print the return code of the previous call
# prints 1, which indicates error/false in shell
(( 1 ))
echo $?
# prints 0, indicating success/true
(( 2 ))
echo $?
# prints 0
(( -1 ))
echo $?
# prints 0
所以括号内的行为与C对true和false的解释是一致的,0表示false,non-zero表示true。 (( ))
将 false“转换”为 return 值 1,将 true 转换为 return 值 0。