web-dev-qa-db-ja.com

UNIXコマンドラインでのUnicode正規化フォーム間の変換

Unicodeでは、一部の文字の組み合わせに複数の表現があります。

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

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

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

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

24
glts

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はShell one linersにはあまり適していませんが、外部スクリプトを作成したくない場合は、次のように実行できます。

$ 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"ääääää"))'
ääääää
7
Nykakin

完全を期すため、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}
4

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'
ä
3
mtt2p

coreutilsには、適切なunormを取得するためのパッチがあります。 4バイトのwcharで私にとってはうまくいきます。従う http://crashcourse.housegordon.org/coreutils-multibyte-support.html#unorm 2バイトのwcharシステム(cygwin、windows、および32ビットのaixとsolaris)の残りの問題コードポイントを上位プレーンからサロゲートペアに、またはその逆に変換する必要があり、基になるlibunistring/gnulibはまだそれを処理できません。

Perlにはunicharsツールがあり、cmdlineでさまざまな正規化形式も実行します。 http://search.cpan.org/dist/Unicode-Tussle/script/unichars

2
rurban

から利用可能なCharlintと呼ばれるPerlユーティリティがあります。

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

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

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

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

2
Захар Joe