如果a小于b, a -lt b不等于正确吗?

时间:2021-07-16 09:37:29

I'm not trained in Linux, but I can muddle through with some doc lookups, but I'm stumped.

我没有接受过Linux的培训,但是我可以通过一些文档查找来应付,但是我被难住了。

I found a script that helps set the date on my dd wrt router when it starts up, but only if the current date is less than the stored date. I can share the whole script if you want, but it boils down to this statement not evaluating to true when I expect it to. I'm putting the literals in, rather than the variables, and it still does not return true, it executes the "else" statement:

我找到了一个脚本,它可以帮助我的dd wrt路由器在启动时设置日期,但前提是当前日期小于存储日期。如果您愿意,我可以共享整个脚本,但它归结为这个语句,当我期望它为true时,它不计算为true。我把文字代入,而不是变量,它仍然没有返回true,它执行"else"语句:

 if [ 021715402012 -lt 021815402012 ]
  then
     echo "the first seems less than the second"
  else
     echo "the first does not seem less than the second for some reason"
  fi

I would expect "the first seems less than the second" but this is not the case... Is it an overflow problem? I tried to make it a string compare like this:

我本以为“第一个似乎比第二个少”,但事实并非如此……是溢流问题吗?我试着把它变成一个字符串比较如下:

if [ x021715402012 -lt x021815402012 ]

and tried putting it in quotes:

试着把它放在引号里

if [ "x021715402012" -lt "x021815402012" ]

it always executes the else. Does "a -lt b" not mean true if a is less than b?

它总是执行else语句。“a -lt b”是否意味着a小于b?

Any insight into this would be appreciated, I'm stumped!

任何对此的见解都将是感激的,我被难住了!

4 个解决方案

#1


3  

The mnemonics such as -lt might be said to come from the original Fortran comparators such as .LT. from the late 1950s.

像-lt这样的助记符可以被认为来自于象. lt这样的原始Fortran比较器。从1950年代末。

Yes, in the shell, -lt does a 'less than' numeric comparison. (Be aware, though, that in Perl, the numeric comparisons are < etc, and the string comparisons are denoted by the alphabetic operators such as -lt!)

是的,在shell中,-lt做一个“小于”的数值比较。(不过要注意,在Perl中,数值比较是< etc,字符串比较是用字母操作符(如-lt!)表示的)。

However, in some, perhaps many, shells the conversion and comparison may well be done in the local long integer format. If you're on a 32-bit machine, the values you quote exceed the 32-bit (signed) range by a factor of 10 or so. On a 64-bit machine, or with a shell that uses long long, you'd be OK.

但是,在一些(可能是很多)中,转换和比较可以很好地以本地长整数格式进行。如果您在一台32位的机器上,您所引用的值将超过32位(已签名)的范围,大约为10倍。在64位机器上,或者使用长时间外壳的情况下,您是可以接受的。

The hex equivalents of the decimal numbers are 021715402012 = 0x50E56BD1C and 021815402012 = 0x5144C9E1C; they can't be octal because of the 8. (However, if the shell does interpret the leading zero as 'octal', then the second number is just 021 or 17 decimal because the 8 ends the octal number. However, the 64-bit shells I tested on (Mac OS X 10.7.3 and RHEL 5) both seemed to treat them as decimal, not octal.)

十进制数的十六进制等价物为021715402012 = 0x50E56BD1C和021815402012 = 0x5144C9E1C;因为8,它们不能是八进制的。(然而,如果壳层确实将前导0解释为“八进制”,那么第二个数字就是021或17小数,因为8结束八进制数。然而,我测试的64位shell (Mac OS X 10.7.3和RHEL 5)似乎都将它们视为十进制,而不是八进制。

The example code below, compiled under 64-bit gives the following output:

下面的示例代码,在64位下编译,给出如下输出:

021715402012 =  240565532 = 0x050E56BD1C
021815402012 =  340565532 = 0x05144C9E1C

Compiled under 32-bit, it gives the following output:

在32位下编译,输出如下:

021715402012 = 2147483647 = 0x007FFFFFFF
021815402012 = 2147483647 = 0x007FFFFFFF

If this was what happened in your shell, then the resulting behaviour of -lt would be explained. You could confirm it by testing whether the two values are -eq; counter-intuitively, this would probably evaluate to true under the hypothesis that you are using a 32-bit shell that limits its arithmetic to long (32-bit) signed integers.

如果这是在您的shell中发生的情况,那么将解释-lt的结果行为。你可以通过测试这两个值是否为-eq来确认;与直觉相反,在假设您使用的是一个32位的shell,将其算法限制为长(32位)的有符号整数时,这可能是正确的。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *array[] = { "021715402012", "021815402012" };
    for (int i = 0; i < 2; i++)
    {
        int j = atoi(array[i]);
        long k = strtol(array[i], 0, 10);
        printf("%-10s = %10d = 0x%.10lX\n", array[i], j, k);
    }
    return 0;
}

#2


1  

What shell and version are you using? Any chance of an embedded control character somewhere? (Try deleting re-typing the code.) On openSUSE 11.2 (x86_64):

您正在使用什么shell和版本?有可能在某处嵌入一个控制字符吗?(尝试删除重新输入代码。)在openSUSE 11.2(x86_64):

$if [ 021715402012 -lt 021815402012 ]; then echo yes; else echo no; fi
yes

Interestingly, though,

有趣的是,尽管如此,

$if [ 012 -lt 11 ]; then echo yes; else echo no; fi
no

This surprises me because man bash says that -lt performs an arithmetic comparison, and a constant with a leading 0 is interpreted as octal. So I'd expect this to test whether ten is less than eleven, because 012 base 8 = 8 + 2.

这让我感到惊讶,因为曼•巴什说-lt执行一个算术比较,一个前导为0的常数被解释为八进制。我希望这个能测试10是否小于11,因为012以8为底= 8 + 2。

Can someone set us straight?

有人能纠正我们吗?

#3


1  

A few things are happening...

有些事情正在发生……

Your shell seems to be using 32-bit arithmetic and your numbers are overflowing the format.

您的shell似乎使用了32位的算术,而您的数字正在溢出这种格式。

Also, all command parameters in shell scripts are strings, so the quotes will have no effect at all unless characters in a parameter are significant to the shell parser.

此外,shell脚本中的所有命令参数都是字符串,因此引号根本没有作用,除非参数中的字符对shell解析器很重要。

The shell if statement is actually running the test(1) command which is linked to [ as a shorthand. (And then it ignores a final ].) Although the command could have used the same operator for numeric and string comparisons, as it happens the command is designed in such a way that the operators assume a certain type, and -lt assumes numeric.

壳牌if语句实际上是运行测试(1)命令与[作为一个速记。(然后它忽略了最后一个]。)尽管命令可以使用相同的操作符对数字和字符串比较,碰巧命令设计以这样一种方式,运营商承担某种类型,和lt假定数字。

On bash and ash (dash) I get an error message on your x... example.

在bash和ash (dash)中,我收到一个关于您的x的错误消息……的例子。

#4


0  

I'm not sure if your particular shell is using this interpretation, but here's what I think is happening:

我不确定你的具体shell是否使用了这个解释,但我认为正在发生的事情是:

021715402012 is an 11-digit octal number. 021815402012 is a two-digit octal number terminated by a non-octal digit (the 8).

021715402012是一个11位的八进制数字。021815402012是一个两位数的八进制数字,以一个非八进制数字(8)结尾。

Of 021715402012 and 021, clearly the second is smaller.

在021715402012年和021年,显然第二个更小。

Regarding your other attempts, the documentation for the test and [ commands indicates that -lt is only valid for numeric arguments, not strings.

关于您的其他尝试,测试的文档和[命令指示-lt只对数值参数有效,而不是字符串。

#1


3  

The mnemonics such as -lt might be said to come from the original Fortran comparators such as .LT. from the late 1950s.

像-lt这样的助记符可以被认为来自于象. lt这样的原始Fortran比较器。从1950年代末。

Yes, in the shell, -lt does a 'less than' numeric comparison. (Be aware, though, that in Perl, the numeric comparisons are < etc, and the string comparisons are denoted by the alphabetic operators such as -lt!)

是的,在shell中,-lt做一个“小于”的数值比较。(不过要注意,在Perl中,数值比较是< etc,字符串比较是用字母操作符(如-lt!)表示的)。

However, in some, perhaps many, shells the conversion and comparison may well be done in the local long integer format. If you're on a 32-bit machine, the values you quote exceed the 32-bit (signed) range by a factor of 10 or so. On a 64-bit machine, or with a shell that uses long long, you'd be OK.

但是,在一些(可能是很多)中,转换和比较可以很好地以本地长整数格式进行。如果您在一台32位的机器上,您所引用的值将超过32位(已签名)的范围,大约为10倍。在64位机器上,或者使用长时间外壳的情况下,您是可以接受的。

The hex equivalents of the decimal numbers are 021715402012 = 0x50E56BD1C and 021815402012 = 0x5144C9E1C; they can't be octal because of the 8. (However, if the shell does interpret the leading zero as 'octal', then the second number is just 021 or 17 decimal because the 8 ends the octal number. However, the 64-bit shells I tested on (Mac OS X 10.7.3 and RHEL 5) both seemed to treat them as decimal, not octal.)

十进制数的十六进制等价物为021715402012 = 0x50E56BD1C和021815402012 = 0x5144C9E1C;因为8,它们不能是八进制的。(然而,如果壳层确实将前导0解释为“八进制”,那么第二个数字就是021或17小数,因为8结束八进制数。然而,我测试的64位shell (Mac OS X 10.7.3和RHEL 5)似乎都将它们视为十进制,而不是八进制。

The example code below, compiled under 64-bit gives the following output:

下面的示例代码,在64位下编译,给出如下输出:

021715402012 =  240565532 = 0x050E56BD1C
021815402012 =  340565532 = 0x05144C9E1C

Compiled under 32-bit, it gives the following output:

在32位下编译,输出如下:

021715402012 = 2147483647 = 0x007FFFFFFF
021815402012 = 2147483647 = 0x007FFFFFFF

If this was what happened in your shell, then the resulting behaviour of -lt would be explained. You could confirm it by testing whether the two values are -eq; counter-intuitively, this would probably evaluate to true under the hypothesis that you are using a 32-bit shell that limits its arithmetic to long (32-bit) signed integers.

如果这是在您的shell中发生的情况,那么将解释-lt的结果行为。你可以通过测试这两个值是否为-eq来确认;与直觉相反,在假设您使用的是一个32位的shell,将其算法限制为长(32位)的有符号整数时,这可能是正确的。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *array[] = { "021715402012", "021815402012" };
    for (int i = 0; i < 2; i++)
    {
        int j = atoi(array[i]);
        long k = strtol(array[i], 0, 10);
        printf("%-10s = %10d = 0x%.10lX\n", array[i], j, k);
    }
    return 0;
}

#2


1  

What shell and version are you using? Any chance of an embedded control character somewhere? (Try deleting re-typing the code.) On openSUSE 11.2 (x86_64):

您正在使用什么shell和版本?有可能在某处嵌入一个控制字符吗?(尝试删除重新输入代码。)在openSUSE 11.2(x86_64):

$if [ 021715402012 -lt 021815402012 ]; then echo yes; else echo no; fi
yes

Interestingly, though,

有趣的是,尽管如此,

$if [ 012 -lt 11 ]; then echo yes; else echo no; fi
no

This surprises me because man bash says that -lt performs an arithmetic comparison, and a constant with a leading 0 is interpreted as octal. So I'd expect this to test whether ten is less than eleven, because 012 base 8 = 8 + 2.

这让我感到惊讶,因为曼•巴什说-lt执行一个算术比较,一个前导为0的常数被解释为八进制。我希望这个能测试10是否小于11,因为012以8为底= 8 + 2。

Can someone set us straight?

有人能纠正我们吗?

#3


1  

A few things are happening...

有些事情正在发生……

Your shell seems to be using 32-bit arithmetic and your numbers are overflowing the format.

您的shell似乎使用了32位的算术,而您的数字正在溢出这种格式。

Also, all command parameters in shell scripts are strings, so the quotes will have no effect at all unless characters in a parameter are significant to the shell parser.

此外,shell脚本中的所有命令参数都是字符串,因此引号根本没有作用,除非参数中的字符对shell解析器很重要。

The shell if statement is actually running the test(1) command which is linked to [ as a shorthand. (And then it ignores a final ].) Although the command could have used the same operator for numeric and string comparisons, as it happens the command is designed in such a way that the operators assume a certain type, and -lt assumes numeric.

壳牌if语句实际上是运行测试(1)命令与[作为一个速记。(然后它忽略了最后一个]。)尽管命令可以使用相同的操作符对数字和字符串比较,碰巧命令设计以这样一种方式,运营商承担某种类型,和lt假定数字。

On bash and ash (dash) I get an error message on your x... example.

在bash和ash (dash)中,我收到一个关于您的x的错误消息……的例子。

#4


0  

I'm not sure if your particular shell is using this interpretation, but here's what I think is happening:

我不确定你的具体shell是否使用了这个解释,但我认为正在发生的事情是:

021715402012 is an 11-digit octal number. 021815402012 is a two-digit octal number terminated by a non-octal digit (the 8).

021715402012是一个11位的八进制数字。021815402012是一个两位数的八进制数字,以一个非八进制数字(8)结尾。

Of 021715402012 and 021, clearly the second is smaller.

在021715402012年和021年,显然第二个更小。

Regarding your other attempts, the documentation for the test and [ commands indicates that -lt is only valid for numeric arguments, not strings.

关于您的其他尝试,测试的文档和[命令指示-lt只对数值参数有效,而不是字符串。