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 --version:GNU bash, version 4.2.45(1)-release (x86_64-pc-linux-gnu)

uname -a:Linux 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 Method for comparison character strings と共通テンプレートの調整可能な順序付けの説明とそれに付随するテンプレート テーブルに記載されていると思います。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 に答える