2013-07-30 16 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 

çıktısı:Koşullu ifade dizeleri nasıl karşılaştırır?

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

cevap

5

Bash kılavuzu söyler:

kullanıldığında [[< ve> operatörler Mevcut yerel ayarı kullanarak sözcüksel olarak rt. Test komutu ASCII sıralamasını kullanarak sıralar.

Bu, (3), sırasıyla strcoll (3) ya da strcmp kullanılarak kaynar.

Bunu test için aşağıdaki programı (strcoll_strcmp.c) kullanın:

#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; 
} 

Not farkı: bu gibi karşılaştırmak neden

$ 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 

Tam emin değilim. Bu, bazı ingilizce sözlük kurallarına bağlı olmalıdır. Kesin kuralların ISO 14651 Method for comparing character strings and description of the common template tailorable ordering ve beraberindeki şablon tablosunda açıklandığını düşünüyorum. Glibc bu verileri, kaynak ağacında libc/localedata/locales'un altında içerir.

+0

Ama neden tek uzay 'a' her iki durumda da daha azdır? – updogliu

+0

cevabım altındaki bir ekleme Bkz @updogliu. – spbnick

+0

Birkaç durum denedim. Lider boşlukların bulunması yeterlidir strcoll' 'de atılır gibi görünüyor. //en.cppreference.com/w/cpp/string/byte/strcoll – updogliu

2

[ ] veya [[ ]] alfabetik sıraya ASCII göre iki dizgileriyle karşılaştırır içinde kullanılan < operatör. Bu, a'un b'dan daha az olduğu anlamına gelir. Buradaki uyarı, [ ]'un biraz zor ve arcane olması nedeniyle <'dan kurtulmanız gerektiğidir, diğer bilge tabanı ise bir yönlendirme yapmak istediğinizi düşünür. Bir uzay ondalık değer 20 sahiptir ve '0' 48.

Yani değeri vardır gibi senin örnek ' a' yılında

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

'0a' daha kesinlikle daha azdır:

iki test

ancak equvivalent vardır Sanırım orada bir böcek buldun.

[ ' a' \< '0a' ] 

ve

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

denk olmalıdır, ve [ ] bir doğrudur. Eğer gözlemliyoruz

4

davranış manual aşağıdaki açıklanabilir:

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

ASCII karşılaştırmaya dayalı karşılaştırma için bakıyor gibi görünüyor. Davranışı, compat32 veya compat40 ayarlayarak değiştirebilirsiniz.

$ 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 
kılavuzda itibaren

:

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. 
İlgili konular