zsh 算术比较给出误报

vis*_*360 3 zsh shell-script arithmetic

为什么将 0 作为参数传递会导致误报(打印“True”)?

#!/bin/zsh

k="$1"

if ((0 < k < 1))
then
    echo "True"
fi
Run Code Online (Sandbox Code Playgroud)

注意这个脚本被称为stitch_applier.sh

终端

% ./stitch_applier.sh 0
True
Run Code Online (Sandbox Code Playgroud)

这是在 Linux 系统上运行的。

ilk*_*chu 10

shell 的算法不支持这样的链式比较。相反,第一个a < b返回10,具体取决于关系是否为真。

因此,如果k0,则((0 < k < 1))((0 < 0 < 1)),与(( (0 < 0) < 1))左关联相同。零不小于零,所以不小于零0 < 0,所以在算术上下文中,0. 然后我们有0 < 1,这是真的,你去吧。

如果要测试是否k在一个范围内,则需要执行((0 < k && k < 1)).

请注意,例如 Bash 和许多其他 shell 仅处理整数算术,并且没有严格介于 0 和 1 之间的整数,因此在这些 shell 中,测试将始终失败。不过,Ksh 和 Zsh 可以处理浮动。


这就是运算符在 C 中的工作方式,所有POSIXBashZsh 都引用算术运算符的 C 定义。(POSIX 只定义了$(( )),not (( )),但是 Bash 和 Zsh 在这两者中对算术的处理是相同的。否则会造成混淆。)

一些较新的语言的工作方式有所不同。Python 以友好着称, 支持链式比较RustC++至少讨论过添加类似的支持。就像 C++ 文档注释一样,无论如何都没有人a < b < c故意使用C 语言。(不过,类似的东西(a < b) != (c < d)可能有用。它会检查其中一个关系是否为真。)Perl 和 GNU awk 似乎给出了1 < 2 < 3.