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


20

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

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

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

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

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


2
로케일에서 정렬 순서가 정의되지 않은 모든 문자의 결과 일 수 있습니다 (따라서 동일한 정렬). Austin 그룹에서 진행중인 관련 토론을 참조하십시오 . 로케일을 C로 변경하여 수정하십시오 .
Stéphane Chazelas

1
죄송합니다, C그것은 단일 바이트 문자가 아니라 여기에하지 않습니다. C.UTF-8가능한 곳에서 할 것입니다.
Stéphane Chazelas

11
축하합니다. 첫 번째 질문에서 Stéphane이 Austin Group 스레드를 사용하는 것을 소환했습니다. 그것은 적어도 인터넷 가치가 있어야합니다. 또는 ⅘ 또는 심지어 ■ 인터넷도 마찬가지입니다. 유닉스 및 리눅스에 오신 것을 환영합니다 . 흥미로운 질문을 계속하십시오.
derobert

답변:


29

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

당신은 또한 알 수 있습니다

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 외부.


1과 2가 다른 또 다른 일반적인 경우는 문자 결합과 같은 것들이 있는 유니 코드 입니다.
Gilles 'SO- 악마 중지'

@Gilles, 문자 결합은 고유 한 문자입니다. 이 조합은 그래 핀 / 셀을 형성하지만 여전히 여러 문자로 구성됩니다. é (U + 00E9)와 e (e 뒤에 U + 0301)는 동일한 그래 핀이지만 두 가지 다른 문자 시퀀스 (적어도 POSIX API 관점에서)입니다. 1과 2에 의해, 그들은 다를 것입니다. U + 0301이 모든 데이터 정렬 가중치를 "IGNORE"로 설정 한 경우 3으로 동일하다고 간주 할 수 있지만 일반적으로 분음 부호의 순서를 결정하려는 경우에는 그렇지 않습니다.
Stéphane Chazelas

일반적으로 같은 문자열 을 고려 é하고 바람직 하지만 바람직 하지는 않습니다 e. POSIX의 데이터 정렬 순서 개념은 거의 맞지 않습니다. 문자를 너무 많이 기반으로하며 문자열을 정렬하는 가장 일반적인 방법을 설명하지 않습니다 (예 : 프랑스어 사전은 단어를 정렬하기 위해 사전 식 순서를 사용하지 않습니다. 그런 다음 악센트를 사용하여 관계를 결정하십시오.
Gilles 'SO- 악마 그만'

@ 질, 예. 그래서 나는 glibc 로케일에서 같은 정렬 순서 (의도적)를 가진 문자가 거의 의미가 없다고 말하고 싶습니다. é vs é는 일반적으로 정규 분해와 같이 문자열에서 먼저 변형을 수행하여 해결됩니다 (대소 문자를 구분하지 않는 정렬 / 매칭을 수행하려는 경우 먼저 소문자로 변환하는 것과 유사 함). 참조 중환자 실 가이드 주제에 대한 좋은 참조를 들어.
Stéphane Chazelas

@Gilles, POSIX 로케일 조합 알고리즘의 가중치는 프랑스어 사전 정렬을 수행 할 수 있습니다. 그것이 무게의 작동 방식입니다. 제 패스 일차 가중치를 사용하여 (동일한 경우)를 검사 억양, 제 3 패스 총액 ... 제 패스 (E 및 E (및 E 및 E)가 동일하고, 결합 급성 억양 무시를 어디)
스테판 Chazelas가를

-3

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

다음 예를 시도하십시오.

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

1
그건 사실이 아니야. POSIX는 연산자 =가 동등성을 검사하는 데 사용되도록 지정합니다 . 문제는 연산자가 아닌 누락 된 따옴표입니다.
scai April

1
또한 "= 연산자는 ==와 같습니다."섹션 man bash에서 말합니다 [[.
michas

1
@scai, POSIX는 [[...]]연산자를 지정하지 않습니다 . 그리고 =와 ==는 쉘에서 구현되었으며 (ksh / bash / zsh) 동일하지 않고 패턴 일치를 위해 동일합니다.
Stéphane Chazelas

패턴과 비교할 때 패턴을 인용해서는 안되며, 그렇지 않으면 리터럴 문자열로 간주되므로 첫 번째 테스트에서 "아니오"입니다.
xhienne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.