unix 명령 행에서 유니 코드 정규화 양식 간 변환


22

유니 코드에서 일부 문자 조합에는 둘 이상의 표현이 있습니다.

예를 들어, 문자 ä 는 다음과 같이 나타낼 수 있습니다.

  • "ä", 즉 코드 포인트 U + 00E4 ( c3 a4UTF-8 인코딩의 2 바이트 ) 또는
  • "ä"는 두 개의 코드 포인트 U + 0061 U + 0308입니다 ( 61 cc 88UTF-8의 3 바이트 ).

유니 코드 표준에 따르면 두 표현은 동일하지만 "정규화 형식"이 다릅니다 ( UAX # 15 : 유니 코드 정규화 형식 참조) .

유닉스 툴박스에는 sed , tr , iconv , Perl 등 모든 종류의 텍스트 변환 툴 이 있습니다. 명령 줄에서 빠르고 쉬운 NF 변환을 수행하려면 어떻게해야합니까?


2
펄을위한 "Unicode :: Normalization"모듈이 이런 종류의 작업을 수행하는 것처럼 보입니다 : search.cpan.org/~sadahiro/Unicode-Normalize-1.16/Normalize.pm
goldilocks

CLI를 가지고 있다면 @goldilocks ... 내 말은 perl -MUnicode::Normalization -e 'print NFC(... 어 , 여기에 무슨 일이야 ...
mirabilos

답변:


20

ICU 에서 uconv유틸리티를 사용할 수 있습니다 . 음역 ( )을 통해 정규화 를 수행합니다 .-x

$ uconv -x any-nfd <<<ä | hd
00000000  61 cc 88 0a                                       |a...|
00000004
$ uconv -x any-nfc <<<ä | hd
00000000  c3 a4 0a                                          |...|
00000003

데비안에서는 우분투 및 기타 파생 상품 uconvlibicu-dev패키지에 포함되어 있습니다. Fedora, Red Hat 및 기타 파생 제품 및 BSD 포트에서는 icu패키지에 있습니다.


감사합니다. 그래도 함께 30M dev 라이브러리를 설치해야합니다. 더 나쁜 것은 uconv 자체에 대한 적절한 문서를 찾을 수 없다는 것입니다. 어디에서 찾았 any-nfd습니까? 이 도구의 개발이 중단 된 것 같습니다. 마지막 업데이트는 2005
있었습니다

2
@glts로 any-nfd표시된 목록을 탐색하여 찾았 습니다 uconv -L.
Gilles 'SO- 악마 그만'

우분투 사용에 sudo apt install icu-devtools실행 uconv -x any-nfc하지만 간단한 문제가 해결되지 , 예 bugText.txt 를 가진 파일은 "이글 레시아는, 나쁜-A는 좋은-A는" 에 의해 변환 uconv -x any-nfc bugText.txt > goodText.txt체류 동일한 텍스트를.
피터 크라우스

7

파이썬은 unicodedata표준 라이브러리에 모듈을 가지고 있으며 , unicodedata.normalize()함수 를 통해 유니 코드 표현을 번역 할 수 있습니다 :

import unicodedata

s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2) 
print(ascii(t1)) 

t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)
print(ascii(t3))

Python 3.x로 실행 :

$ python3 test.py
True
'Spicy Jalape\xf1o'
True
'Spicy Jalapen\u0303o'

파이썬은 쉘 하나의 라이너에는 적합하지 않지만 외부 스크립트를 만들고 싶지 않은 경우 수행 할 수 있습니다.

$ python3 -c $'import unicodedata\nprint(unicodedata.normalize("NFC", "ääääää"))'
ääääää

Python 2.x의 경우 인코딩 줄 ( # -*- coding: utf-8 -*-) 을 추가 하고 문자열을 u 문자로 유니 코드로 표시해야합니다.

$ python -c $'# -*- coding: utf-8 -*-\nimport unicodedata\nprint(unicodedata.normalize("NFC", u"ääääää"))'
ääääää

3

hexdump 도구로 확인하십시오.

echo  -e "ä\c" |hexdump -C 

00000000  61 cc 88                                          |a..|
00000003  

iconv로 변환하고 hexdump로 다시 확인하십시오.

echo -e "ä\c" | iconv -f UTF-8-MAC -t UTF-8 |hexdump -C

00000000  c3 a4                                             |..|
00000002

printf '\xc3\xa4'
ä

2
이것은 macOS에서만 작동합니다. Linux, FreeBSD 등에는 'utf-8-mac'이 없습니다. 또한이 인코딩을 사용한 분해는 사양을 따르지 않습니다 (하지만 macOS 파일 시스템 정규화 알고리즘을 따릅니다). 더 많은 정보 : search.cpan.org/~tomita/Encode-UTF8Mac-0.04/lib/Encode/…
antonone

질문에 OS가 지정되어 있지 않아도 @antonone이 공정합니다.
roaima

1
@roaima 그렇기 때문에 유닉스 / 리눅스 기반의 모든 시스템에서 답이 작동한다고 가정했습니다. 위의 답변은 macOS에서만 작동합니다. macOS 관련 답변을 찾고 있다면 부분적으로 효과가 있습니다. 나는 다른 날에 왜 utf-8-mac리눅스 가 없는지 궁금하고 이것이 정상적인 지 궁금해하기 때문에 시간을 잃어 버렸기 때문에 그 점을 지적하고 싶었습니다 .
antonone

3

완전성을 위해 perl:

$ perl -CSA -MUnicode::Normalize=NFD -e 'print NFD($_) for @ARGV' $'\ue1' | uconv -x name
\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}
$ perl -CSA -MUnicode::Normalize=NFC -e 'print NFC($_) for @ARGV' $'a\u301' | uconv -x name
\N{LATIN SMALL LETTER A WITH ACUTE}

2

coreutils에는 적절한 패치가 있습니다 unorm. 4 바이트 wchars에서 나에게 잘 작동합니다. http://crashcourse.housegordon.org/coreutils-multibyte-support.html#unorm 따르십시오 나머지 문제는 2 바이트 wchar 시스템 (32 비트의 cygwin, windows, plus aix 및 solaris)이며 코드 포인트를 상단에서 변환해야합니다 대리 쌍으로 평면을 배치하고 그 반대도 마찬가지이며, 기본 libunistring / gnulib는 아직 처리 할 수 ​​없습니다.

perl에는 unicharscmdline에서 다양한 정규화 양식을 수행 하는 도구가 있습니다. http://search.cpan.org/dist/Unicode-Tussle/script/unichars


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.