特殊変数 $^I の使い方
1つのディレクトリに含まれる大量のファイルに対して、一括で変更を行いたい場合
my $target = "*.dat"; @ARGV = glob $target or die; $^I = ".bak"; # これがスイッチ while(<>) { s/(^Date:).*/\1 2009-8-10/; # Date ヘッダを 8/10 にして s/^Phone: .*\n//; # 電話番号行を消して。 print; } unlink glob $target or die; # 無事終わったら後始末
ワンライナーだと
% perl -p -i.bak -w -e 's/Kamei/John/g' *.dat
こんなん。
@ARGV を使わないといけないってのが何ともアレな感じではあるが、すげー便利であることは否めない。実際使う場合は @ARGV が変わんないように、ブロックで囲んで
{ ... local @ARGV = glob $target or die; ... }
としといた方がいいだろう。
関数にするんなら、無名関数を引数にとって、
sub replace_all { my ($func, $file_glob) = @_; local @ARGV = glob "$file_glob" or return 0; local $^I = ".bak"; my $cnt = 0; while(<>) { $cnt += $func->(); print; } unlink glob "$file_glob.bak" or die; return $cnt; }
ってかんじか。呼び出し元は、以下のような感じで、*.dat のファイルの中に現れる "singer" という文字列を全部 "writer" に置換する感じ。
replace_all(sub{ s/singer/writer/g }, "*.dat");
こういうのシンプルに書けるのが Perl のいいとこだなーと思う。