はじめに
uconv
は ICU が開発した文字変換のコマンドです。文字コードを変換したり、全角を半角に変換したり、大文字を小文字に変換したり、ひらがなをカタカナに変換したりする場合、tr
コマンドや nkf
コマンドを使って変換するという例を多く見かけます。しかし tr
コマンドは Unicode に対応していなかったり POSIX ロケール以外の対応に問題があったりします。また nkf
コマンドは Network Kanji Filter の略であることからもわかるように基本的に日本語にしか対応していません。そういった時に使えるのが uconv
コマンドです。uconv
コマンドはあらゆる国の文字種や文字コード変換に対応しており、Unicode 正規化や BOM の追加や削除にも対応しています。
tr
コマンドは標準でインストールされているというメリットがありますが、日本語に対応する必要があるシェルスクリプトで、コマンドのインストールが可能な環境であれば tr
コマンドや nkf
コマンドの代わりに uconv
を使うと良いでしょう。文字コード変換の iconv
コマンドで有名な ICU プロジェクトのコマンドなので多くの POSIX に準拠している環境に移植されており、一般的なパッケージ管理システムからインストールできるはずです。
tr
コマンドの問題点
# macOS (BSD版) (注意 「あ-ん」では全てのひらがなが変換されるわけではありません)
$ echo ぁあいうえおゔ | tr "あ-ん" "ア-ン"
ぁアイウエオゔ
# Linux (GNU版) (Unicode 非対応)
$ echo ぁあいうえおゔ | tr "あ-ん" "ア-ン"
]��]�]]��]��]��]��]]�
uconv
コマンドの例
結構いろんな変換ができます。この記事ではすべてを紹介しているわけではないので、-x
オプションで指定する変換規則 (Transliteration) についての詳細は「Transforms | ICU Documentation」を参照してください。
文字コードの変換
uconv
は iconv
や nkf
と同じように文字コードの変換を行うことができます。文字コードの変換として使う場合、オプションは iconv
と互換性があるように設計されており簡単に置き換えることができます。もちろん Shift JIS や EUC-JP だけではなく、世界中の文字コードに対応しています。uconv -l
で対応している文字コード一覧を出力することができます。
$ echo あいう | uconv -f UTF-8 -t SHIFT_JIS | nkf --guess
Shift_JIS (LF)
$ uconv -l # 対応している文字コード一覧を出力
(大量にあるので省略)
注意 nkf --guess
は変換後の文字コードの確認のためだけに使用しています。
半角を全角に変換
$ echo アイウエオabcde | uconv -x "Halfwidth-Fullwidth"
アイウエオabcde
全角を半角に変換
$ echo アイウエオ | uconv -x "Fullwidth-Halfwidth"
アイウエオ
カタカナのみを半角から全角に変換
Unicode プロパティが使用できます。
$ echo アイウエオabcde | uconv -x "\p{katakana} Halfwidth-Fullwidth"
アイウエオabcde
大文字に変換
$ echo abcde | uconv -x "upper"
ABCDE
ひらがなをカタカナに変換
$ echo あいうえお | uconv -x katakana
アイウエオ
カタカナをひらがなに変換
$ echo アイウエオ | uconv -x hiragana
あいうえお
指定した範囲のみの変換
$ echo ABCDEABCDE | uconv -x "[A-C] lower"
abcDEabcDE
複数の変換を一度に行う
大文字変換⇒全角変換といった一連の変換も一コマンドで実行できる。
注意 単純に複数の変換を繋げられるわけではないようです。何をどう組み合わせられるのかよく分かっていません。
$ echo abcde | uconv -x "upper; Halfwidth-Fullwidth"
ABCDE
特定の文字を変換
$ echo abc | uconv -x 'b>ビー'
aビーc
文字削除(tr -d 相当)
$ echo abcde | uconv -x '[b-d] remove'
ae
以下の方法でも可能
$ echo abcde | uconv -x '[b-d] >;'
ae
最初の一文字だけ大文字化
echo abc | uconv -x 'title'
Abc
以下の方法でも可能
echo abc | uconv -x '^(.) > &upper($1)'
Abc
文字単位の変換
文字の順番を入れ替え、さらに片方だけ大文字化しています。
$ echo abcd | uconv -x '(.)(.) > &upper($2)$1'
BaDc
ローマ字変換
$ echo aiueo | uconv -x hiragana
あいうえお
制御文字を名前で出力
$ printf 'a\tb' | uconv -x '\p{Cc} any-name'
a\N{<control-0009>}b%
注意 最後の %
は出力が改行で終わらない場合に zsh がそれを知らせるためにつけているものです。
Unicode 正規化 (NFD, NFC, NFKD, NFKC)
Unicode 正規化 を行うことが出来ます。
$ echo ガガ | uconv -x NFD # ef bd b6 ef be 9e e3 82 ab e3 82 99
ガガ
$ echo ガガ | uconv -x NFC # ef bd b6 ef be 9e e3 82 ac
ガガ
$ echo ガガ | uconv -x NFKD # e3 82 ab e3 82 99 e3 82 ab e3 82 99
ガガ
$ echo ガガ | uconv -x NFKC # e3 82 ac e3 82 ac
ガガ
と言いたいところなのですが、2023-06-15: ICU 73.2 時点で(おそらく)バグにより NFC / NFKC が機能しない文字があります。
$ # 「が」はNFCできる
$ printf が | uniname
character byte UTF-32 encoded as glyph name
0 0 00304C E3 81 8C が HIRAGANA LETTER GA
$ printf が | uconv -x nfd | uconv -x nfc | uniname
character byte UTF-32 encoded as glyph name
0 0 00304C E3 81 8C が HIRAGANA LETTER GA
$ # 「ガ」はNFCできない
$ printf ガ | uniname
character byte UTF-32 encoded as glyph name
0 0 0030AC E3 82 AC ガ KATAKANA LETTER GA
$ printf ガ | uconv -x nfd | uconv -x nfc | uniname
character byte UTF-32 encoded as glyph name
0 0 0030AB E3 82 AB カ KATAKANA LETTER KA
1 3 003099 E3 82 99 ゙ COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
カタカナの濁点の場合がだめとか言うわけではなく、特定の文字だけ NFC / NFKC が機能しないので謎です。以下の [ ] の文字が正しく機能しない文字です。
がぎぐげござじずぜぞだぢづで[ど][ば][ぱ]びぴぶぷ[べ][ぺ]ぼぽゔゞ
[ガ][ギ][グ]ゲゴザジ[ズ][ゼ][ゾ][ダ]ヂヅデドバパビピブプベペボポヴ[ヷ]ヸヹヺ[ヾ]
NFC / NFKC を使いたい場合は、Perl か Ruby を使うのがおすすめです。どちら標準モジュールで動作し、短く書くことが出来ます。
$ printf ガ | uconv -x nfd | perl -MUnicode::Normalize -CS -pe '$_=NFC($_)' | uniname
character byte UTF-32 encoded as glyph name
0 0 0030AC E3 82 AC ガ KATAKANA LETTER GA
$ printf ガ | uconv -x nfd | ruby -pe '$_.unicode_normalize!(:nfc)' | uniname
character byte UTF-32 encoded as glyph name
0 0 0030AC E3 82 AC ガ KATAKANA LETTER GA
インストール方法
macOS
brew install icu4c
.zshrc などで環境変数 PATH を設定する
export PATH="/usr/local/opt/icu4c/bin:$PATH"
Debian
sudo apt install icu-devtools
RedHat
sudo yum install icu