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


20

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

arg1 OP arg2

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

或算术表达式:

<= >= < > 比较

== != 平等与不平等

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

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

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


1
= != < <= > >=比较字符串1 -eq 01但是1 != 018 -lt 42但是8 > 42
dave_thompson_085 '16

它们在算术表达式中超载。
蒂姆(Tim)

1
您必须在bash更改日志中进行搜索,以了解何时添加了每个功能。我怀疑算术表达式的添加时间比测试命令晚得多。
glenn jackman

我不是在问比较字符串。@muru。
蒂姆

Answers:


28

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

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

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

    因为它们也位于测试命令内和内[[ ]]

    是的,这里面的成语,=<等都是字符串运算符。

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

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

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

if (( 2 > 1 )); then ...

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

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

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

什么时候使用?

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

比较两个整数时,这两种方法是否可以始终互换使用?

对于两个数字,我不得不说是。
但是对于变量,扩展,数学运算,可能存在一些关键差异,应该有利于彼此。我不能说绝对是平等的。首先,(( ))可以依次执行几个数学运算:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi

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

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


1
=是一个赋值,==是算术扩展的比较。问题正确引用了它。但是答案是错误的。
ceving

12

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

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

在1980年代的某个时候test在Korn shell中,算术表达式也比命令晚。他们遵循C语言的语法,C语言在Unix界很流行。因此,他们用c的运算符:==为平等,<=对于较少的或相等的等

Unix Seventh Edition没有算术表达式,但是它有exprcommand,它还对整数运算(包括比较运算符)实现了类似于C的语法。在shell脚本中,必须加上<和字符>以保护它们不受shell的影响,例如if expr 1 \< 2; …等价于if test 1 -lt 2; …。在外壳上添加算术表达式使大多数使用expr作废了,因此今天它并不为人所知。

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

if [ "$((x + y))" -lt "$z" ]; then 

在ksh,bash或zsh脚本中,((…))两者都可以使用。

if ((x + y < z)); then 

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


1

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

在纸上,我们进行字符串/数字比较时没有过多考虑。另一方面,计算机不知道987是数字还是字符串。您需要不同的操作员告诉计算机该怎么做,以便获得正确的结果。有一些额外的信息在这里,解释了一些历史。本质上,这些变量是无类型的,并且为了历史兼容性而保留了这种方式。


在我的帖子中,= !=是算术运算符,而联机帮助页test仅显示条件表达式运算符。
蒂姆(Tim)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.