比较整数:算术表达式或条件表达式

Tim*_*Tim 37 shell bash history arithmetic test

在 Bash 中,可以使用条件表达式比较两个整数

ARG1 OP ARG2

OP是一个-eq-ne-lt-le-gt,或-ge。如果arg1 分别等于、不等于、小于、小于或等于、大于或大于或等于arg2,则这些算术二元运算符返回 true 。Arg1arg2可以是正整数或负整数。

或算术表达式:

<= >= < > 比较

== != 平等与不平等

为什么我们有两种不同的方法来比较两个整数?什么时候用哪个?

例如,[[ 3 -lt 2 ]]使用条件表达式,并(( 3 < 2 ))使用算术表达式。当比较为真时两者都返回 0

比较两个整数时,这两种方法可以互换使用吗?如果是,为什么 Bash 有两种方法而不是一种方法?

小智 46

是的,我们有两种不同的方法来比较两个整数。

似乎这些事实在本论坛中并未被广泛接受:

  1. 里面的成语[ ]进行算术比较的经营者-eq-ne-lt-le-gt-ge

    因为它们也在测试命令中,并且在[[ ]].

    是的,在这个习语中=<, 等是字符串运算符。

  2. 里面的成语(( ))进行算术比较的经营者==!=<<=>,和>=

    不,这不是“算术扩展”(以 a 开头$)作为$(( ))。它在 man bash 中被定义为“复合命令”。

    是的,它遵循“算术扩展”的相同规则(内部),但没有输出,只有退出值。它可以像这样使用:

if (( 2 > 1 )); then ...
Run Code Online (Sandbox Code Playgroud)

为什么我们有两种不同的方法来比较两个整数?

我猜后者(( ))是作为一种更简单的算术测试方法而开发的。它与 几乎相同,$(( ))但只是没有输出。

为什么是两个?好一样,为什么我们有两个printf(外置和内置)或四个测试(对外test,内置test[[[)。这就是贝壳生长的方式,一年内改善某些区域,第二年改善其他区域。

什么时候用哪个?

这是一个非常棘手的问题,因为不应该存在有效差异。当然,a[ ]工作和(( ))内部工作的方式有一些差异,但是:比较两个整数哪个更好?任何人!。

比较两个整数时,这两种方法可以互换使用吗?

对于两个数字,我不得不说是。
但是对于变量、扩展、数学运算,可能存在应有利于其中之一的关键差异。我不能说两者绝对是平等的。一方面,(( ))可以按顺序执行几个数学运算:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi
Run Code Online (Sandbox Code Playgroud)

如果是,为什么 Bash 有两种方法而不是一种方法?

如果两者都有帮助,为什么不呢?

  • 此外 `(` 不是 bash 中的保留字,因此不需要在 `((`,而不是 `[` 或 `[[` (2认同)

Gil*_*il' 16

从历史上看,该test命令首先存在(至少可以追溯到1979 年的Unix 第七版)。它使用了运营商=!=比较字符串,并且-eq-ne-lt等来比较数字。例如,test 0 = 00是假的,但是test 0 -eq 00是真的。我不知道为什么选择这种语法,但可能是为了避免使用<and >,shell 会将其解析为重定向运算符。test几年后,该命令获得了另一种语法:[ … ]相当于test ….

[[ … ]]条件的语法,在其内部<>可以用作操作者无需引用,后来被加入,在ksh中。它与 保持向后兼容[ … ],因此它使用相同的运算符,但添加了<>来比较字符串(例如,[[ 9 > 10 ]]但是[[ 9 -lt 10 ]])。有关更多信息,请参阅使用单括号或双括号 - bash

在 1980 年代的某个时候,算术表达式也出现在 Korn shell 中test命令之后。它们遵循在 Unix 圈子中非常流行的 C 语言的语法。因此,他们使用 C 的运算符:相等、小于或等于等。==<=

Unix Seventh Edition 没有算术表达式,但它有expr命令,它也为整数运算实现了类似 C 的语法,包括它的比较运算符。在 shell 脚本中,字符<>必须被引用以保护它们不受 shell 的影响,例如if expr 1 \< 2; …相当于if test 1 -lt 2; …. 将算术表达式添加到 shell 使大多数用途expr都已过时,因此今天并不为人所知。

在 sh 脚本中,您通常会使用算术表达式来计算整数值并[ … ]比较整数。

if [ "$((x + y))" -lt "$z" ]; then …
Run Code Online (Sandbox Code Playgroud)

在 ksh、bash 或 zsh 脚本中,您可以同时使用((…))两者。

if ((x + y < z)); then …
Run Code Online (Sandbox Code Playgroud)

[[ … ]]如果您想使用涉及整数以外的条件的条件,则该表单很有用。


小智 2

根据测试手册页,= 和 != 用于字符串比较,而表达式 -eq、-gt、-lt、-ge、-le 和 -ne 是整数比较。我在编写 shell 脚本时一直遵循这个约定,而且它总是有效的。请注意,如果表达式中有变量,则可能需要以某种方式引用变量以避免进行空比较。

在纸面上,我们不假思索地进行字符串/数字比较。另一方面,计算机不知道 987 是数字还是字符串。您需要不同的操作员告诉计算机该做什么,以便获得正确的结果。这里有一些附加信息解释了一些历史。本质上,这些变量是无类型的,并且为了历史兼容性而保持这种状态。