2013-07-30 13 views
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

答えて

5

バッシュマニュアルは言う:

で使用する場合[[、<及び>オペレーター現在のロケールを使用して辞書的に辞書を作成します。テストコマンドは、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 comparing character strings and description of the common template tailorable orderingと付属のテンプレートテーブルに記載されていると思います。 Glibcにはこのデータがソースツリーの libc/localedata/localesに含まれています。

+0

しかし、なぜ単一のスペースには、「」どちらの場合に比べて少ないのですか? – updogliu

+0

@updogliu私の答えの一番下に追加を見てください。 – spbnick

+0

私はいくつかのケースを試しました。先頭の空白は単に '' strcoll''で破棄されたようです。 – updogliu

2

[ ]または[[ ]]の中では、<オペレータを使用すると、2つの文字列がASCIIアルファベット順に比較されます。つまり、ab未満です。 [ ]はちょっと難しく、あなたは<をエスケープする必要があるので、他の賢明なベースはあなたがリダイレクトをしたいと思うからです。

2つのテストがしかしequvivalentある:あなたの例では

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

スペースは小数点値20を持ち、「0」だから値48

を持っているよう' a'が、'0a'よりも間違いなく小さいです私はあなたがそこにバグを見つけたと思う。

[ ' a' \< '0a' ] 

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

同等であり、[ ]内の1つが正しいはずです。あなたが観察している

4

挙動はmanualから、次で説明することができます。

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 ‘<’ and ‘>’ 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 ‘<’ and ‘>’ operators (see previous item) and the effect of interrupting a command list. 
関連する問題