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

uname -a : Linux 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

[ ] 또는 [[ ]] 내에서 사용되는 < 연산자는 ASCII 알파벳 순서에 따라 두 문자열을 비교합니다. 이는 ab보다 작음을 의미합니다. 여기에주의해야 할 것은 [ ]이 다소 어려우며 무언가가 < 인 탈출구가 필요하기 때문에 다른 현명한 기지에서는 리디렉션을 원한다고 생각하기 때문입니다. 공간 소수점 값 (20)을 가지고 있으며, '0'(48)

그래서 값이 있기 때문에, 당신의 예를 ' a'에서

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

'0a'보다 확실히 작 :

두 시험

그러나 equvivalent 있습니다 거기에 버그를 발견했다고 생각합니다.

[ ' a' \< '0a' ] 

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

은 동일해야하며, [ ]의 한 올. 당신이 관찰하고

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. 
관련 문제