grep 또는 sed가 일부 UTF-8 문자를 인식할 수 없습니다

grep 또는 sed가 일부 UTF-8 문자를 인식할 수 없습니다

파일의 모든 문자를 식별해 보십시오.

파일에는 다음 sample이 포함됩니다.

a eɪ
abandon əˈbændən
ability əˈbɪləti
able ˈeɪbəl
able ˈeɪbl
abortion əˈbɔrʃən
abortion əˈbɔrʃn
about əˈbaʊt
above əˈbʌv
abroad əˈbrɔd

로케일이 올바르게 설정되었는지 확인하십시오.

$ echo $LANG

en_US.UTF-8

두 번째 필드에 대한 명령을 가져와서 문자별로 나누고 그 수를 세어보세요.

$ cat sample | awk '{print $2}' | grep -o . | sort | uniq -c | sort -n

  1 a
  1 æ
  1 i
  1 v
  2 d
  2 t
  3 e
  3 l
  3 ɔ
  3 r
  4 n
  9 b
 11 ə
 17 ɪ

ʃ그리고 어디 ˈ? 결합 문자나 특별한 내용은 없습니다. 다른 UTF-8 문자(예 ɔ: , ə및 )도 가져옵니다.ɪ

그런데 사용 결과 는 "\n" 줄을 추가한다는 점을 제외하면 sed 's/\(.\)/\1\n/g'거의 동일합니다 .grep -o .

내가 놓친 것이 있나요? grep에는 숨겨진 UTF-8 옵션이 있습니까?

중요한 경우 Ubuntu 12.04.2 LTS.

답변1

문제는 로케일의 데이터 정렬 정보 에 sort있으며 이를 사용하는 것입니다. uniq두 명령 모두에 대해 로케일을 끄는 것이 유효합니다.

cat sample | awk '{print $2}' | grep -o . | LC_ALL=C sort | LC_ALL=C uniq -c | sort -n
      1 ʊ
      1 ʌ
      1 a
      1 æ
      1 i
      1 v
      2 ʃ
      2 d
      2 t
      3 e
      3 l
      3 ɔ
      3 r
      4 ɪ
      4 n
      9 ˈ
      9 b
     11 ə

답변2

그러나 "C" 로케일을 사용하면 수동 정렬이 손실됩니다(예: "a"와 "A"를 동등하게 만드는 것).

glibc 로케일 데이터에서 처리되지 않는 특정 문자를 대조하고 처리해야 하는 경우 기본 대조를 확장하여 고유한 로케일을 만들 수 있습니다.

현재 로케일(예: /usr/share/i18n/locales/en_US)의 정의를 다른 이름으로 복사할 수 있습니다. 그런 다음 편집하세요. LC_COLLATE 섹션에는 다음이 있습니다.

LC_COLLATE
copy "iso14651_t1"

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-end

END LC_COLLATE

컴파일하세요. 그러면 대신 localedef -f ./yourmodifiedfile -t UTF-8 ./someplace 사용할 수 있습니다 .LC_ALL=./someplaceLC_ALL=C

정기적으로 사용하려면 다른 표준 로케일(보통 /usr/share/locale 또는 /usr/lib/locale)로 생성한 디렉토리를 넣고 표준 방식으로 이름을 지정하세요(예: en_US를 기반으로 하는 경우). 예를 들어 "en_US@IPA"이고 로케일을 영구적으로 LC_COLLATE=en_US@IPA로 설정할 수 있습니다(특정 LC_* 변수를 개별적으로 정의하려는 경우 LC_ALL을 정의하면 안 됩니다).

또한 U+02C8은 수정자이므로 데이터 정렬에서 올바르게 무시되어야 합니다. 그러나 이를 별도의 문자로 처리해야 하는 경우 다음을 사용할 수 있습니다(ASCII 작은따옴표는 U+02C8(뷰 구성에 사용됨)과 동일합니다. 이렇게 입력하는 경우가 많기 때문입니다).

# defines a handy symbol, to group together similar chars
collating-symbol <'>

# define 
reorder-after <z>
<'>

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-after <'>
<U0027> <'>;<BAS>;IGNORE;IGNORE
<U02C8> <'>;<PCL>;IGNORE;IGNORE

reorder-end

행은 다음과 같습니다. <unicode value> <1st level>;<2d level>;<3d level>;<4th level> 레벨은 행을 정렬하는 데 사용되는 레벨입니다.

제 생각에는 (해보지는 않았지만 연습으로 남겨두었습니다 :)) 마지막 레벨만 정의하면 정렬할 때 대부분 무시되지만 고유한 관점에서는 여전히 "다릅니다"(체인이 모든 레벨은 고유하며 캐릭터도 마찬가지라고 생각합니다.)

일반적으로 첫 번째 수준은 e와 같은 모든 문자와 같은 그룹화 기호입니다. 두 번째 수준은 일반적으로 기본 문자에 사용되며 다양한 악센트 버전과 (특별?) "특수" 문자에 사용되는 여러 다른 기호와 함께 사용됩니다. 3D 수준은 대문자와 소문자를 구별하는 데 자주 사용됩니다.

관련 정보