パスワードを忘れた? アカウント作成
13553976 journal
UNIX

passer-byの日記: GB2312 のメール

日記 by passer-by

ここ何年か、時々 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

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

計算機科学者とは、壊れていないものを修理する人々のことである

読み込み中...