ここ何年か、時々 GB2312 と銘打ったメールを受け取ることがあって(英語メールに返信する形で Shift_jis に含まれない文字を含むメールを書くと、一部のメーラで生成されるらしい)、mutt で読むのに苦労していた。iconv で文字コードを GB2312 と指定しても、色々と文字化けして読めなかったりする。
調べてみると、やはり難儀した先人たちがちゃんと解決してくれていた。要するに GB2312 と言いつつ実はそれを拡張した GBK という文字セットになってるらしく、それは更に GB18030 に拡張されて中国の正式文字コードになってるという事。なので、iconv -f GB18030 -t UTF8 するとすんなり読めた。
なお、Shift_JIS や EUC-JP 環境を使ってる人は、これを更に nkf -W8 とかで受けて使うと良い。というのも、iconv は出力側文字セットに含まれてない文字を受け取ると、そこで動作を止めてしまうから。nkf なら -I オプションで ISO-2022-JP に無い文字は「〓」に変換してくれるし、知らない文字はそのまま放置して更に先に進もうと頑張ってくれる。nkf 偉い。
という訳で、以下のように日本語文字コードだけ nkf を使う変換フィルタをシェルスクリプトをでっちあげて使用中:
#!/bin/sh
# usage: $0 -f CODESET_FROM -t CODESET_TO [[[input] input] ...]
#
# いわゆる二条項BSDライセンスで。(2018-04-30 追記)
# 可能なら著作権放棄でいきたいものですが。
# parse the -f and -t options, and remove them from $*
while getopts f:t: name
do
case $name in
f) INCODE=$(echo $OPTARG | tr A-Z a-z);;
t) OUTCODE=$(echo $OPTARG | tr A-Z a-z);;
esac
done
shift $(($OPTIND - 1))
case ${INCODE:=iso-2022-jp} in
sjis|shift-jis|shift_jis)
CMD="nkf -SX"
;;
ujis|euc-jp|eucjp)
CMD="nkf -EX"
;;
iso-2022-jp*)
CMD="nkf -JX"
;;
utf-8|utf8) # entry added on 2018-04-02
CMD="nkf -WX"
;;
gb2312) # subset of GB18030, which includes Japanese and Korean characters.
CMD="iconv -f gb18030 -t utf-8"
;;
*)
CMD="iconv -f $INCODE -t utf-8"
;;
esac
case ${OUTCODE:=utf-8} in
sjis|shift-jis|shift_jis)
if [ "${CMD%% *}" = nkf ]; then
CMD="$CMD -sI $@" # -I added on 2018-04-02
else
CMD="$CMD $@ | nkf -W8X -sI"
fi
;;
ujis|euc-jp|eucjp)
if [ "${CMD%% *}" = nkf ]; then
CMD="$CMD -eI $@" # -I added on 2018-04-02
else
CMD="$CMD $@ | nkf -W8X -eI"
fi
;;
iso-2022-jp*)
if [ "${CMD%% *}" = nkf ]; then
CMD="$CMD -jI $@" # -I added on 2018-04-02
else
CMD="$CMD $@ | nkf -W8X -jI"
fi
;;
utf-8|utf8) # entry added on 2018-04-02
if [ "${CMD%% *}" = nkf ]; then
CMD="$CMD -w $@"
else
CMD="iconv -f $INCODE -t $OUTCODE $@"
fi
;;
*)
CMD="iconv -f $INCODE -t $OUTCODE $@"
;;
esac
if [ $INCODE = $OUTCODE ]; then
CMD="cat $@"
fi
eval "$CMD"
拙いコードなのはしょうがないとして、ちゃんと POSIX compliant になってるかがちょっと心配。
(追記)nkf だけを使うときに -I フラグを忘れていたのを追加。utf-8 対応エントリを入出力共に忘れていたのを追加。on 2018-04-02