[unix] bash의 예기치 않은 문자와 일치하는 대괄호 표현식 (범위 없음)

Linux에서 bash를 사용하고 있습니다. 다음 if 문에서 성공을 거두었지만 실패 코드를 반환해서는 안됩니까?

if [[  = [⅕⅖⅗] ]] ; then echo yes ; fi

사각형은 문자와 같지 않으므로 성공 코드를 얻는 이유를 알 수 없습니다.

필자의 경우 이중 괄호를 유지하는 것이 중요합니다.

이 시나리오에서 범위를 수행하는 다른 방법이 있습니까?



답변

그것은 동일한 정렬 순서를 가진 캐릭터의 결과입니다.

당신은 또한 알 수 있습니다

sort -u << EOF




EOF

한 줄만 반환합니다.

또는:

expr  = 

POSIX에 필요한 경우 true를 반환합니다.

GNU 시스템과 함께 제공되는 대부분의 로케일에는 동일한 정렬 순서를 갖는 여러 문자 (및 문자 시퀀스 (소트 순서))가 있습니다. ■ ⅕⅖⅗의 경우 순서가 정의되지 않았기 때문에 순서가 정의되지 않은 문자는 GNU 시스템에서 동일한 정렬 순서를 갖습니다. Ș 및 Ş와 같은 정렬 순서를 갖는 것으로 명시 적으로 정의 된 문자가 있습니다 (물론 어쨌든 실제 논리 나 일관성에 대한 일관성은 없습니다).

그것은 매우 놀랍고 가짜 행동의 원천입니다. 나는 한 오스틴 그룹에서 최근에 문제를 제기 (POSIX와 단일 UNIX 사양 뒤에 몸) 메일 링리스트 및 토론은 여전히 2015년 4월 3일의로 진행된다.

이 경우, [y]일치하는 x위치 xy정렬 여부 는 확실하지 않지만 대괄호 표현식은 배열 요소와 일치하기 때문에 bash동작이 예상 됨을 나타냅니다 .

어쨌든, 나는 [⅕-⅕]적어도 [⅕-⅖]일치해야 한다고 생각 합니다 .

서로 다른 도구가 다르게 동작하는 것을 알 수 있습니다. ksh93은 bashGNU 처럼 동작 grep하거나 sed그렇지 않습니다. 일부 다른 쉘은 yash버그가 더 많은 다른 동작을 가지고 있습니다 .

일관된 동작을하려면 모든 문자가 다르게 정렬되는 로캘이 필요합니다. C 로케일이 일반적인 것입니다. 그러나 대부분의 시스템에서 C 로케일의 문자 세트는 ASCII입니다. GNU 시스템에서는 일반적으로 C.UTF-8UTF-8 문자를 작업하는 데 사용할 수 있는 로케일에 액세스 할 수 있습니다.

그래서:

(export LC_ALL=C.UTF-8; [[  = [⅕⅖⅗] ]])

또는 동등한 표준 :

(export LC_ALL=C.UTF-8
 case  in ([⅕⅖⅗]) true;; (*) false; esac)

거짓을 반환해야합니다.

또 다른 대안은 LC_COLLATEGNU 시스템에서 작동하는 C 로만 설정 하는 것이지만 멀티 바이트 문자의 정렬 순서를 지정하지 못하는 다른 시스템에서는 반드시 그렇지는 않습니다.


그 중 하나의 교훈은 평등 이 문자열을 비교할 때 기대하는 것만 큼 명확한 개념이 아니라는 것입니다. 평등은 가장 엄격함에서 가장 엄격함을 의미 할 수 있습니다.

  1. 동일한 바이트 수와 모든 바이트 구성 요소의 값이 동일합니다.
  2. 동일한 문자 수와 모든 문자가 동일합니다 (예 : 현재 문자 집합에서 동일한 코드 포인트 참조).
  3. 두 문자열은 로케일의 데이터 정렬 알고리즘과 동일한 정렬 순서를 갖습니다 (즉, a <b 또는 b> a 모두 참이 아님).

이제 2 또는 3의 경우 두 문자열에 유효한 문자가 있다고 가정합니다. UTF-8 및 일부 다른 인코딩에서 일부 바이트 시퀀스는 유효한 문자를 형성하지 않습니다.

1과 2는 그 때문에 또는 일부 문자가 둘 이상의 가능한 인코딩을 가질 수 있기 때문에 반드시 동등한 것은 아닙니다. 일반적으로 ISO-2022-JP와 같은 상태 저장 인코딩의 경우 또는 A로 표현 될 수 있습니다 ( ASCII로 전환하는 시퀀스이므로 원하는 수만큼 삽입 할 수 있지만 차이는 없습니다). 이러한 유형의 인코딩이 여전히 사용 중일 것으로 기대하지 않으며 GNU 도구는 일반적으로 해당 형식에서 제대로 작동하지 않습니다.411b 28 42 411b 28 42

또한 대부분의 비 GNU 유틸리티는 0 바이트 값 (ASCII의 NUL 문자)을 처리 할 수 ​​없습니다.

어떤 정의 가 사용되는지는 유틸리티 및 유틸리티 구현 또는 버전에 따라 다릅니다. POSIX는 100 % 명확하지 않습니다. C 로케일에서 3 개 모두 동일합니다. 그 YMMV 외부.


답변

당신이 잘못 =하고 ==있으며 동일하지 않습니다.

다음 예를 시도하십시오.

if [[ "■" == "[⅕⅖⅗]" ]] ; then echo yes ; else echo no ; fi

if [[ "1" == "1" ]] ; then echo yes ; else echo no ; fi

if [[ "■" == "■" ]] ; then echo yes ; else echo no ; fi


답변