Perl

Data::Dumper の日本語文字化けと Syntax::Collector。

More than 3 years have passed since last update.

古いメモより。

Data::Dumper のメモと、Syntax::Collector のメモくっつけたら、 後者の方が長かった、、、


Data::Dumper の日本語文字列の扱いを変更させる。

use Data::Dumper したら文字化けする、っての対応。

{

package Bar ;
use Data::Dumper ;
no warnings 'redefine' ;
*Data::Dumper::qquote = sub { return shift } ;
$Data::Dumper::Useperl = 1 ;
}

use Data::Dumper ;
use utf8 ;
my $v = '日本語文字列' ;
print Dumper \$v ;

まあ、別に、パッケージを分ける必要もないけれど。



  • qquote を再定義して、処理させない。


  • $Data::Dumper::Useperl = 1 して、XS 使わない。

「Dump する文字列は、全て UTF-8 フラグ付いてますよ。」って自信がある人は、

use Encode ;

*Data::Dumper::qquote = sub { return encode "utf8", shift ;} ;

とすると、

Wide character in print at なエラーは避けられます。


Syntax::Collector

これらのコードをいちいち書くのが面倒な人への一例として。


install

plenv でローカルにインストールしてる環境で。

$ cpanm Syntax::Collector


Syntax.pm

package Syntax ;

use Data::Dumper ;
use Encode ;
no warnings 'redefine' ;
*Data::Dumper::qquote = sub { return encode "utf8", shift ;} ;
$Data::Dumper::Useperl = 1;

use Syntax::Collector <<EOF;
# core modules
use strict 0 ;
use warnings 0;
use autodie 0;
use Data::Dumper 0 ;
use utf8 0 ;
EOF

1;


実行コード

Syntax.pm と同じディレクトリにて。

use Syntax ;

my $v = '日本語文字列' ;
print Dumper $v ;
print $v . "\n" ;

とでもして確認してみる。


グローバルな特殊変数とか。

上の例で分る通り、グローバルな特殊変数とか、グローバルなモジュール由来の変数とかに関しては、Syntax.pm の中で設定してしまうのが吉。

以下に二つ程、追加の例を


setlocale

まあ、(シェルの方の) $LANG 変えちゃうのが楽だとは思うんだけど、簡単な例として。

package Syntax ;

use POSIX qw( setlocale LC_ALL ) ;
setlocale( LC_ALL, 'C' ) ;
use Syntax::Collector <<EOF;
use POSIX 0 qw( strftime ) ;
EOF

1;

$ perl -le 'print strftime( "%A, %B %d, %Y", localtime );' -MPOSIX=strftime

木曜日, 11月 05, 2015
$ perl -le 'print strftime( "%A, %B %d, %Y", localtime );' -MSyntax
Thursday, November 05, 2015


@INC

ちょっと複雑な例として。

実行スクリプト CODE.pl との関係で、

/PATH/TO

+--/APP
+--CODE.pl
+--/lib
+--A.pm
+--Sytax.pm
+--/lib
+--B.pm

こんな関係を常に保っていて、/PATH/TO も流動する場合1に、A.pm, B.pm を、きちんと use する。


Sytax.pm


/PATH/TO/APP/lib/Sytax.pm

package Syntax ;

use Cwd 'realpath' ;
use File::Basename ;
BEGIN{ shift @INC } ;
use lib (
+( dirname realpath __FILE__ ) ,
+( realpath +( dirname realpath __FILE__ ) . q{/../../lib} )
) ;

use Syntax::Collector <<EOF;
use Data::Dumper 0 ;
use A 0 ;
use B 0 ;
EOF

1;



A.pm/B.pm


/PATH/TO/APP/lib/A.pm

package A ;

print "A\n" ;
1;


/PATH/TO/lib/B.pm

package B;

print "B\n" ;
1;


CODE.pl


/PATH/TO/APP/CODE.pl

use File::Basename ;

use lib +( dirname __FILE__ ) . q{/lib} ;
use Syntax ;

print Dumper \@INC


適当な場所で実行

$ perl /PATH/TO/APP/CODE.pl

A
B
$VAR1 = [
'/PATH/TO/APP/lib',
'/PATH/TO/lib',
'${PLENV_ROOT}/versions/5.18.4/lib/perl5/site_perl/5.18.4/darwin-2level',
'${PLENV_ROOT}/versions/5.18.4/lib/perl5/site_perl/5.18.4',
'${PLENV_ROOT}/versions/5.18.4/lib/perl5/5.18.4/darwin-2level',
'${PLENV_ROOT}/versions/5.18.4/lib/perl5/5.18.4',
'.'
];



  • @INC はグローバル



    • @INC の、 . は、最初から存在を無視する事。


    • use lib@INC の最初に追加されるので、 CODE.pl 側からの登録分は一応 shift で削る。


    • @INC 登録分が、全て絶対パスなので、あとは use し放題。




  • __FILE__ は現在のファイルの事。





  1. NFS マウントして、マウントポントは別名。双方それぞれ利用するとか。