📘

【Bash】uconv で濁音・半濁音を NFC/NFD に変換する

2024/06/13に公開
2

uconv は ICU によって開発された文字変換ツールである。Debian の場合 icu-devtools パッケージに含まれている。文字情報を調べてくれる uniname が含まれる uniutils と一緒にインストールする

sudo apt install icu-devtools uniutils

「ぱ」を NFD に変換してみる。基底文字と結合文字の組み合わせになる。

echo -n| uconv -x NFD | LINES=35 uniname
character  byte       UTF-32   encoded as     glyph   name
        0          0  00306F   E3 81 AF       は      HIRAGANA LETTER HA
        1          3  00309A   E3 82 9A       ゚      COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK

uconv をつなげて生成された文字のコードポイントを求めることができる

echo -n| uconv -x NFD | uconv -x Hex/Unicode; echo
U+306FU+309A

今度は od コマンドを使ってバイト列を表示してみる

echo -n| uconv -x NFD | od -tx1 -An
 e3 81 af e3 82 9a

大文字変換も加えてみる

echo -n| uconv -x NFD | od -tx1 -An | tr [:lower:] [:upper:]
 E3 81 AF E3 82 9A

xxd でもバイト列表示ができる

echo -n| uconv -x NFD | xxd -p -u
E381AFE3829A

xxd の出力結果を調整してみる

str=$(echo -n| uconv -x NFD | xxd -p -u)
masakielastic@penguin:~$ for (( i = 0; i < ${#str}; i += 2 )); do echo -n "${str:$i:2} "; done; echo;
E3 81 AF E3 82 9A 

なお uconv は濁点・半濁点以外に旧字体を新字体に変換してしまうので、大量の文字を変換する場合にはプログラミング言語で正規表現で変換対象をひらがかなカタカナに絞る必要がある

echo| uconv -x NFD 

Discussion

ko1nksmko1nksm

一部の文字は NFC が正しく動作しないので注意してください。

$ echo -n ぱ | od -tx1
0000000 e3 81 b1
0000003

$ echo -n ぱ | uconv -x NFD | uconv -x NFC | od -tx1
0000000 e3 81 af e3 82 9a
0000006

$ echo -n ぴ | uconv -x NFD | uconv -x NFC | od -tx1
0000000 e3 81 b4
0000003

代替方法の例です。

$ echo -n| uconv -x NFD | perl -MUnicode::Normalize -CS -pe '$_=NFC($_)' | od -tx1
0000000 e3 81 b1
0000003

$ echo -n| uconv -x NFD | ruby -pe '$_.unicode_normalize!(:nfc)' | od -tx1
0000000 e3 81 b1
0000003

いつ修正されるのやら

https://unicode-org.atlassian.net/jira/software/c/projects/ICU/issues/ICU-22413