Bash 3.2中逻辑或||运算符在算术表达式中的行为

5

我在最新的Mac OS上进行了一项实验,使用了一个名为"a.sh"的Shell脚本,并且脚本内容如下(完全复制)。

#!/bin/bash
echo $BASH_VERSION
a=0
(( a < 100 || 1 / a < 2 )) && echo ok

我得到了:

3.2.57(1)-release
./a.sh: line 4: ((: a < 100 || 1 / a < 2 : division by 0 (error token is "< 2 ")

既然 a < 100 已经是 true,我认为 1 / a < 2 不会被计算。

有人能帮助我理解一下吗?


3
我无法在Bash 5上重现这个问题,你使用的是哪个版本? - oguz ismail
3
在 https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html 上没有任何内容表明在算术表达式中的 || 会进行短路运算;也许它确实不会进行短路运算?(我承认这很令人惊讶。) - ruakh
1个回答

6

出现此错误有两种情况:

  1. Bash 3.2.57在算术表达式中评估逻辑 or 的两个侧。

  2. 或者因为您使用了单一的位运算符号 | ,而不是双重的逻辑运算符号 ||

LC_ALL=C bash -c 'a=0; (( a < 100 | 1 / a < 2 )) && echo ok'

解释:运行Bash脚本时发生错误,表达式中存在除数为零的情况,错误的标记是"a < 2"。
LC_ALL=C bash -c 'a=0; (( a < 100 || 1 / a < 2 )) && echo ok'

ok

原因:

| 是按位 运算符。

当用于:

a < 100 | 1 / a < 2

按位 运算如下:

100 | 1

这在二进制中等同于 01100100 ∨ 0000000101100101 二进制或 101 十进制。

最终结果是:

a < 100 | 1 / a < 2 等同于:

a < 101 / a < 2

a=0

0 < 101 / 0 < 2


谢谢您的帮助。我编辑了问题以使shell版本清晰明了。这可能是一个版本兼容性问题,因为它对您有效。感谢您提供关于“||”和“|”的额外信息。 - Joe Smith
@JoeSmith 我在Bash 3.2.57中重现了这个问题,所以显然这是该版本的特定行为。无论如何,我意识到在Bash算术上下文中,1 / a < 2将始终为真,因为它只处理整数→ 1/ℕ始终<1。 - Léa Gris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接