2017/09/19

いまだに Data::Dumper で消耗しているの?

Data::Dumper::AutoEncode というモジュールがありまして、主に printデバッグのお供に便利な変数のダンプモジュール君です。
デファクトスタンダードであるところの Data::Dumper でダンプすると「\x{304a}\x{3067}\x{3093}」こんな感じにエスケープされてしまうマルチバイトな文字列を、 Data::Dumper::AutoEncodeeDumper という関数を使うと、自動的にエンコードして普通に読める状態で出力してくれます。

use utf8;
use Data::Dumper::AutoEncode; # export `eDumper` and `Dumper`

my $foo = +{ bar => 'おでん' };

print Dumper($foo);
# { bar => "\x{304a}\x{3067}\x{3093}" }

print eDumper($foo);
# { bar => "おでん" }

さらに「\x{304a}\x{3067}\x{3093}」この出力を文字列操作で元に戻す edumper というコマンドも同梱されているのでちょっと便利です。

以下のように、普通の Dumper による出力があったとして、

$ perl hoge.pl
$VAR1 = [
          "\x{304a}\x{3067}\x{3093}"
        ];

edumper にパイプすると、

$ perl hoge.pl | edumper
$VAR1 = [
          "おでん"
        ];

という風に戻してくれます。いぇい!

さて、前置きが長かったのですが、この Data::Dumper::AutoEncode は、スカラーかリファレンス変数のリストを受け取り、値は基本全て decoded であることを期待していました。そもそも decoded なものを encoded にするのが目的ですし、近年の Perl アプリケーションにおいてはそういう扱いが普通なのでそうしていたのですが、けっこう混ざってる場面もあるらしく、そういう場面で Data::Dumper::AutoEncode を利用すると、もともと encoded な文字列で2重にエンコードしてしまってわりと悲惨な結果になっていたようなので、このたびめでたく修正しました。

しかし、デフォルトでは encoded な文字列に対してもこれまで通り2重エンコードします。なぜならその方が中身がどうなってるかわかるからです。encoded/decoded混ぜてる方が特殊事情との判断。混ぜちゃってる人は $Data::Dumper::AutoEncode::CHECK_ALREADY_ENCODED = 1 すると幸せになれます。まあとはいえ、decoded のものはエンコードされ、そうでないものはそのままとなると Data::Dumper::AutoEncode が自動的にエンコードしたのか、もともと encoded な文字列なのか判別がつかないということになります。それは困るわー困るわーという人向けに、FLAG_STR も設定できるようになりました。

use utf8;
use Data::Dumper::AutoEncode;

local $Data::Dumper::AutoEncode::CHECK_ALREADY_ENCODED = 1;
local $Data::Dumper::AutoEncode::FLAG_STR = 'auto_encoded:';

my $foo = +{ bar => 'おでん' };

print eDumper($foo);
# { bar => "auto_encoded:おでん" }

eDumper によって encoded にされた文字列に、設定したプレフィックス文字列が足されるわけです。これで一目瞭然ですね。ちなみに、デフォルトだと何も足されません。我こそはうっかりさんという人だけ設定すれば十分でしょうから。

なお、私は設定しています。

というわけで、現場からは以上です。

サイト内検索