例えばこういうの*1。
use strict; use warnings; use Encode; my $utf8str = "あいらとふれあ、コラボっちゃお(ハート)"; Encode::_utf8_off($utf8str); my $sjisstr = encode('cp932', decode('utf8', $utf8str)); print $sjisstr;
$ perl a.pl あいらとふれあ、コラボっちゃお?
デフォルトの挙動としては、encodeの際に変換出来なかった文字は"?"になります。
If CHECK is 0, encoding and decoding replace any malformed character with a substitution character. When you encode, SUBCHAR is used.
Encode - character encodings in Perl - metacpan.org
SUBCHARというのが"?"になってるみたいですね。
文字として扱う分には"?"で問題ないのですが、これをファイル名として使っている場合は困る。Windowsでは"?"をファイル名にできないので、Perlからファイルは作れるものの、オープンしようとするとエラーになってしまいます。
で。調べてみて初めて知ったのですが、encode/decode系の関数には第三引数で上手く変換できなかった(malformed)文字に対するハンドラーを定義できるみたいです。
そしてEncode 2.12以降のバージョンではcode referenceも指定できるみたいです。これは便利すぎる。
ということで、encodeの第三引数をこんな感じにしてみます。
my $sjisstr = encode('cp932', decode('utf8', $utf8str), sub{sprintf "x%04X", shift});
$ perl a.pl あいらとふれあ、コラボっちゃおx2661
おおー。これはすごい。
*1:コード中の"(ハート)"は中抜きハート"♡"が入ります