bash - 双括号构造如何在 bash 中工作?
问题描述
我在这里读到双括号允许 C 风格的变量操作。但是,当我尝试比较字符串时,它没有按预期工作:
(( "a" == "b" )) && echo yes || echo no
# shows yes
我也很困惑如何将变量用作布尔值。按照链接答案中的示例,我尝试了以下操作:
true=1
false=0
a=true
(( a )) && echo yes || echo no
# shows yes
a=false
(( a )) && echo yes || echo no
# shows no
但不会a
是真假的字符串值吗?
此外,由于在 bash 中将“无错误”值 (0) 视为 true,并且将任何“错误”值(非零)视为 false,为什么看起来这里采用了相反的约定?
解决方案
需要注意的主要事情是双括号结构允许算术评估和扩展,并且不是内联 C 解释器。因此,只有 Shell Arithmetic中定义的规则适用,也就是说,只有整数类型的 C 运算在双括号中有效。
第一个例子:bash 构造首先展开
算术运算符之外的任何内容首先根据 bash 规则进行扩展,例如引号、参数扩展、bash 范围{1..5}
和列表{a,b}
结构,然后再开始计算双括号。
在第一个示例中,双引号导致里面的内容被解释为一个单词(在双括号内无效)并且还评估以 $ 开头的内容(但引号内没有),所以第一个示例简单地变成了(( 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.
笔记
$(( ))
当您比较密切相关的和(( ))
构造时,会有一些特殊性。前者(算术扩展)将表达式视为在双引号内,而后者则不是,如上所述。
第二个例子:右值位置的变量递归扩展
Shell Arithmetic中有一些微妙的规则:
- “变量的值在被引用时被计算为算术表达式”
- “或者当一个已经被赋予整数属性的变量
declare -i
被赋值时”。 - “在不使用参数扩展语法的情况下按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0”
在尝试了一下之后,您会发现这基本上意味着 rvalue 中的任何变量都将被递归评估,直到它达到一个整数或未定义/空变量名的值:
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 对真假的解释是一致的,0 表示假,非零表示真。(( ))
将 false“转换”为返回值 1,将 true 转换为返回值 0。
推荐阅读
- batch-file - 有没有办法使用 Anaconda 提示符运行批处理文件
- angular - 将对象从 Angular8 发送到 Spring Boot
- python - 如何为多个文本文件创建词频矩阵?
- android - recyclerview jetpack 错误 - 按两次后退按钮以转到上一个片段
- angular - 当应用程序处于前台时,Angular 8 firebase 推送通知不起作用
- jquery - 在 if 条件下比较输入值
- c++ - 具有特定参数的函子的概念或特征?
- javascript - 是否可以在 Java 中“沙箱化”JavaScript 引擎?
- c# - “不安全”范围的嵌套会影响性能吗?
- node.js - 在 MongoDB NodeJS 的一个查询中更新多条记录,没有任何循环