Shell:如果a小于b,"a -lt b"是不是真的?

Bri*_*n B 6 linux shell

我没有接受过Linux的培训,但我可以通过一些文档查找来解决问题,但我很难过.

我找到了一个脚本,它有助于在启动时在我的dd wrt路由器上设置日期,但前提是当前日期小于存储日期.如果你愿意,我可以分享整个脚本,但是归结为这个声明在我预期的时候没有评估为真.我将文字放入,而不是变量,它仍然不返回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
Run Code Online (Sandbox Code Playgroud)

我希望"第一个似乎不到第二个",但事实并非如此......这是一个溢出问题吗?我试着把它变成一个像这样的字符串比较:

if [ x021715402012 -lt x021815402012 ]
Run Code Online (Sandbox Code Playgroud)

并试着把它放在引号中:

if [ "x021715402012" -lt "x021815402012" ]
Run Code Online (Sandbox Code Playgroud)

它总是执行其他.a -lt b如果a小于b," "不是真的吗?

对此有任何见解将不胜感激,我很难过!

Jon*_*ler 3

可以说,助记符-lt来自.LT.20 世纪 50 年代末的原始 Fortran 比较器。

是的,在 shell 中,-lt进行“小于”数字比较。(但请注意,在 Perl 中,数字比较是<等,字符串比较由字母运算符表示,例如-lt!)

然而,在某些(也许是许多)shell 中,转换和比较很可能以本地长整数格式完成。如果您使用的是 32 位计算机,则您引用的值会超出 32 位(有符号)范围 10 倍左右。在 64 位机器上,或者使用使用 的 shell long long,就可以了。

十进制数的十六进制等效值是 021715402012 = 0x50E56BD1C 和 021815402012 = 0x5144C9E1C;由于 8,它们不能是八进制。(但是,如果 shell 确实将前导零解释为“八进制”,则第二个数字只是十进制的 021 或 17,因为 8 结束了八进制数。但是,64-我测试过的位 shell(Mac OS X 10.7.3 和 RHEL 5)似乎都将它们视为十进制,而不是八进制。)

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

021715402012 =  240565532 = 0x050E56BD1C
021815402012 =  340565532 = 0x05144C9E1C
Run Code Online (Sandbox Code Playgroud)

在 32 位下编译,它给出以下输出:

021715402012 = 2147483647 = 0x007FFFFFFF
021815402012 = 2147483647 = 0x007FFFFFFF
Run Code Online (Sandbox Code Playgroud)

如果这就是您的 shell 中发生的情况,那么所产生的行为-lt就可以解释。您可以通过测试这两个值是否为来确认-eq;与直觉相反,假设您使用的 32 位 shell 将其算术限制为long(32 位)有符号整数,则这可能会评估为 true。

#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;
}
Run Code Online (Sandbox Code Playgroud)