unixコマンドラインでUnicode正規化形式を変換する


22

Unicodeでは、いくつかの文字の組み合わせに複数の表現があります。

たとえば、文字äは次のように表すことができます

  • 「ä」、つまりコードポイントU + 00E4(c3 a4UTF-8エンコーディングで2バイト)、または
  • 「ä」、つまり2つのコードポイントU + 0061 U + 0308(61 cc 88UTF-8で3バイト)。

Unicode標準によれば、2つの表現は同等ですが、異なる「正規化形式」です。UAX#15:Unicode正規化形式を参照してください。

UNIXツールボックスには、sedtriconv、Perlのようなあらゆる種類のテキスト変換ツールがあります。コマンドラインですばやく簡単にNF変換を行うにはどうすればよいですか?


2
この種のものやるべきperlに関する「ユニコード::正規化」モジュールがあるように見えますが:search.cpan.org/~sadahiro/Unicode-Normalize-1.16/Normalize.pmは
ゴルディロックス

@goldilocksにCLIがあった場合...つまり、そうですperl -MUnicode::Normalization -e 'print NFC(...
えーと、

回答:


20

ICUuconvからユーティリティを使用できます。音訳によって正規化が実現されます()。-x

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

Debian、Ubuntu、およびその他の派生物でuconvは、libicu-devパッケージに含まれています。Fedora、Red Hat、およびその他の派生物、およびBSDポートでは、icuパッケージに含まれています。


これは機能します、ありがとう。ただし、30M開発ライブラリをインストールする必要があります。さらに悪いことに、私はuconv自体の適切なドキュメントを見つけることができませんでした:どこで見つけましたany-nfdか?このツールの開発は中止されたようです。最終更新は2005
でした。– glts

2
@gltsでany-nfd表示されたリストを参照して見つけましたuconv -L
ジル「SO-悪であるのをやめる」

Ubuntuのsudo apt install icu-devtools実行uconv -x any-nfcに使用しますが、最も単純な問題を解決しません。たとえば、「Iglésias、Bad-á、Good-á」が同じテキストのままで変換されたbugText.txt ファイル。uconv -x any-nfc bugText.txt > goodText.txt
ピータークラウス

7

Pythonのunicodedata標準ライブラリにはモジュールがあり、unicodedata.normalize()関数を使用してUnicode表現を変換できます。

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'

Pythonはシェルワンライナーにはあまり適していませんが、外部スクリプトを作成したくない場合は実行できます。

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

Python 2.xの場合、エンコード行(# -*- coding: utf-8 -*-)を追加し、文字列をu文字のUnicodeとしてマークする必要があります。

$ 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は公平です。
ロアイマ

1
@roaimaはい、だからこそ、答えはUnix / Linuxベースのすべてのシステムで機能するはずだと思ったのです。上記の答えはmacOSでのみ機能します。macOS固有の答えを探しているなら、それは部分的には機能します。先日、なぜutf-8-macLinux を使用していないのか、これが正常なのか疑問に思っていたので、それを指摘したかっただけです。
アントノン

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。4byte wcharsでうまく動作します。http://crashcourse.housegordon.org/coreutils-multibyte-support.html#unormに従ってください 。残りの問題は、2バイトのwcharシステム(cygwin、windows、32ビットのaixおよびsolaris)であり、上位からコードポイントを変換する必要があります。サロゲートペアへのプレーン、およびその逆、および基礎となるlibunistring / gnulibはまだそれを処理できません。

perlにはunicharsツールがあり、コマンドラインでさまざまな正規化フォームも実行します。http://search.cpan.org/dist/Unicode-Tussle/script/unichars


2

Charlintというperlユーティリティがあります。

https://www.w3.org/International/charlint/

あなたが望むことをします。また、ファイルをダウンロードする必要があります

ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt

最初の実行後、Charlintがそのファイル内の互換性のないエントリについて不平を言うのが見えるので、UnicodeData.txtからこれらの行を削除する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.