7
#!/usr/bin/env bash
echo 'Using conditional expression:'
[[ ' ' < '0' ]] && echo ok || echo not ok
[[ ' a' < '0a' ]] && echo ok || echo not ok
echo 'Using test:'
[ ' ' \< '0' ] && echo ok || echo not ok
[ ' a' \< '0a' ] && echo ok || echo not ok

输出是:

Using conditional expression:
ok
not ok
Using test:
ok
ok

bash --versionGNU bash, version 4.2.45(1)-release (x86_64-pc-linux-gnu)

uname -aLinux linuxmint 3.8.0-19-generic

4

3 回答 3

5

Bash手册说:

当与 [[ 一起使用时,< 和 > 运算符使用当前语言环境按字典顺序排序。test 命令使用 ASCII 排序。

这归结为分别使用 strcoll(3) 或 strcmp(3)。

使用以下程序 (strcoll_strcmp.c) 对此进行测试:

#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");

    if (argc != 3) {
        fprintf(stderr, "Usage: %s str1 str2\n", argv[0]);
        return 1;
    }

    printf("strcoll('%s', '%s'): %d\n",
           argv[1], argv[2], strcoll(argv[1], argv[2]));
    printf("strcmp('%s', '%s'): %d\n",
           argv[1], argv[2], strcmp(argv[1], argv[2]));

    return 0;
}

注意区别:

$ LC_ALL=C ./strcoll_strcmp ' a' '0a'
strcoll(' a', '0a'): -16
strcmp(' a', '0a'): -16

$ LC_ALL=en_US.UTF-8 ./strcoll_strcmp ' a' '0a'
strcoll(' a', '0a'): 10
strcmp(' a', '0a'): -16

究竟为什么这些比较,我不确定。这一定是由于某些英语词典排序规则造成的。我认为确切的规则在ISO 14651 比较字符串的方法和通用模板可定制排序的描述以及随附的模板表中进行了描述。Glibc 在源代码树的libc/localedata/locales.

于 2013-07-30T09:46:39.697 回答
4

您观察到的行为可以通过手册中的以下内容进行解释:

bash-4.1 and later use the current locale’s collation sequence and strcoll(3).

您似乎正在寻找基于 ASCII 排序规则的比较。compat32您可以通过设置或来更改行为compat40

$ cat test
shopt -s compat40
echo 'Using conditional expression:'
[[ ' ' < '0' ]] && echo ok || echo not ok
[[ ' a' < '0a' ]] && echo ok || echo not ok
echo 'Using test:'
[ ' ' \< '0' ] && echo ok || echo not ok
[ ' a' \< '0a' ] && echo ok || echo not ok
$ bash test
Using conditional expression:
ok
ok
Using test:
ok
ok

从手册:

compat32
If set, Bash changes its behavior to that of version 3.2 with respect to locale-specific string comparison when using the ‘[[’ conditional command’s ‘&lt;’ and ‘&gt;’ operators. Bash versions prior to bash-4.0 use ASCII collation and strcmp(3); bash-4.1 and later use the current locale’s collation sequence and strcoll(3). 
compat40
If set, Bash changes its behavior to that of version 4.0 with respect to locale-specific string comparison when using the ‘[[’ conditional command’s ‘&lt;’ and ‘&gt;’ operators (see previous item) and the effect of interrupting a command list. 
于 2013-07-30T10:06:17.910 回答
2

<运算符在内部使用时或[ ]根据[[ ]]ASCII 字母顺序比较两个字符串。这意味着a小于b。这里需要注意的是,因为[ ]你需要逃跑有点困难和神秘<,其他明智的基地认为你想做重定向。

然而,这两个测试是等价的:

[ 'a' \< 'b' ] && echo ok
[[ 'a' < 'b' ]] && echo ok

在您的示例' a'中肯定小于'0a',因为空格的十进制值为 20,而“0”的值为 48。

所以我认为你在那里发现了一个错误。

[ ' a' \< '0a' ]

[[ ' a' < '0a' ]]

应该是等价的,其中一个[ ]是正确的。

于 2013-07-30T09:51:20.850 回答