Go 言語による Unicode 半角/全角変換
もう2年近く前の記事だが,「Go 言語と Unicode 正規化」の脚注でこっそり「単に全角・半角変換ができればいいのなら golang.org/x/text/
width
パッケージをお勧めする」と書いていたのだが,今回はその話。
golang.org/x/text/width パッケージ
golang.org/x/text/
width
パッケージ1 では半角/全角変換用に以下の width
.Transformer
が用意されている。
var (
// Fold is a transform that maps all runes to their canonical width.
//
// Note that the NFKC and NFKD transforms in golang.org/x/text/unicode/norm
// provide a more generic folding mechanism.
Fold Transformer = Transformer{foldTransform{}}
// Widen is a transform that maps runes to their wide variant, if
// available.
Widen Transformer = Transformer{wideTransform{}}
// Narrow is a transform that maps runes to their narrow variant, if
// available.
Narrow Transformer = Transformer{narrowTransform{}}
)
width
.Widen
が全角変換用, width
.Narrow
が半角変換用である。
たとえば,半角変換なら
fmt.Println(width.Narrow.String("1234567890アイウエオカキクケコABCDEFGHIJK"))
//Outpput
//1234567890アイウエオカキクケコABCDEFGHIJK
全角変換なら
fmt.Println(width.Narrow.String("1234567890アイウエオカキクケコABCDEFGHIJK"))
//Outpput
//1234567890アイウエオカキクケコABCDEFGHIJK
のように変換される。
io
.Reader
を使うなら
r := bytes.NewBufferString("1234567890アイウエオカキクケコABCDEFGHIJK")
tr := transform.NewReader(r, wdth.Widen)
buf := new(bytes.Buffer)
io.Copy(buf, tr)
fmt.Println(buf)
//Outpput
//1234567890アイウエオカキクケコABCDEFGHIJK
ってな感じで書ける。
面白いのは width
.Fold
で,半角カナ文字は全角に,全角英数字は半角に,いい感じに変換してくれるのだ。
fmt.Println(width.Fold.String("1234567890アイウエオカキクケコABCDEFGHIJK"))
//Outpput
//1234567890アイウエオカキクケコABCDEFGHIJK
width
.Fold
は, Unicode 正規化と異なり,「神と神2」のような異体字は
fmt.Println(width.Fold.String("神と神"))
//Outpput
//神と神
と影響を受けない3。 ブラボー!
ちなみに Unicode の円記号(YEN SIGN)は,通常文字(半角相当)が「¥:U+00A54」で全角文字が「¥:U+FFE5」である。
JIS ラテン文字(JIS X 0201)の半角円記号(0x5C)は機械的に変換しても同じ値の「\
(REVERSE SOLIDUS)」のままなので(当たり前だけど)ご注意を5。
そろそろ JIS ラテン文字のことは忘れていいかもねー。
spiegel-im-spiegel/text に組み込んでみた
というわけで,この Unicode 半角/全角変換機能を私作の spiegel-im-spiegel/text v0.5.0 に組み込んでみた。 こんな感じに使える。
res := width.Reader(bytes.NewBufferString("1234567890アイウエオカキクケコABCDEFGHIJK"), width.Fold)
buf := new(bytes.Buffer)
io.Copy(buf, res)
fmt.Println(buf)
// Output:
// 1234567890アイウエオカキクケコABCDEFGHIJK
あと,このパッケージの CLI 実装用に作った「nkf っぽいなにか」にもサブコマンド width
として組み込んでいる。
$ gonkf width -h
Convert character width of text (UTF-8 text only)
Usage:
gonkf width [flags] [text file]
Flags:
-f, --form string form of width [fold|narrow|widen] (default "fold")
-h, --help help for width
-o, --output string output file path
$ echo 1234567890アイウエオカキクケコABCDEFGHIJK | gonkf width -f fold
1234567890アイウエオカキクケコABCDEFGHIJK
たとえば Sjift-JIS テキストに対して機能をパイプで繋いで
$ cat sjis.txt
1234567890アイウエオカキクケコABCDEFGHIJK
$ gonkf conv -s sjis sjis.txt | gonkf nwline -f lf | gonkf width -f fold > utf8.txt
$ cat utf8.txt
1234567890アイウエオカキクケコABCDEFGHIJK
みたいな変換もできる(画面はイメージですw
)。
これで概ね spiegel-im-spiegel/text でやりたいことはやり尽くしたかな。
ブックマーク
- Goで全角/半角変換する - Qiita : こちらは内部に変換辞書を持っているらしい
参考図書
- プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- Alan A.A. Donovan (著), Brian W. Kernighan (著), 柴田 芳樹 (翻訳)
- 丸善出版 2016-06-20
- 単行本(ソフトカバー)
- 4621300253 (ASIN), 9784621300251 (EAN), 4621300253 (ISBN), 9784621300251 (ISBN)
- 評価
著者のひとりは(あの「バイブル」とも呼ばれる)通称 “K&R” の K のほうである。この本は Go 言語の教科書と言ってもいいだろう。
-
“width” って日本人には発音しにくいよね。「IT業界で横行する恥ずかしい英語発音」でもネタになるほど(笑) ↩︎
-
ブラウザやブラウザの設定によっては「神」が上手く表示できないようです。 最初の「神」は「
U+FA19 '神'
」で CJK 互換文字です。2番目の「神」が通常の「U+795E '神'
」です。 ↩︎ -
Unicode 正規化と異体字の問題については「Go 言語と Unicode 正規化」を参照のこと。 ↩︎
-
円記号「¥:U+00A5」のコード・ポイントは ISO-8859-1 (Latin-1) で割り当てられている円記号のコードと同じ。というか,そもそも Unicode は ISO-8859-1 と親和するように設計されているのでこうなっているのだが。円記号が ISO-8859-1 に収録されていて(8ビット空間に収まっていて)よかったね,というべきか(笑) ↩︎
-
この辺の事情は韓国語の WON SIGN「₩:U+20A9」とかでも同じらしい。 ↩︎