perlを使いこなす(2)
複数ファイルの連続処理
連続処理専用のフィルターを書く
例えば、次のようなフィルターを考えてみます。
#! /usr/local/bin/perl
# ren
@files = glob("*.jpg");
foreach $files (@files) {
($name, $extention) = split(/\./, $files);
chomp($extention);
$extention =~ s/jpg/jpeg/ig;
$new = $name.".".$extention;
rename($files, $new);
print "$files renamed to $new\n";
}
カレントディレクトリにあるJPG画像のファイル名を、.jpgから.jpegに書き換えるプログラムです。ディレクトリ内にある複数のファイルに、連続して同じ処理を行いたい場合、いちいち(フィルター名 < なんたら > かんたら)とやっていては気が遠くなります。そこで、ディレクトリにあるファイルから条件に合う(この場合なら".jpg"というファイル名の)ファイルをすべて抜き出して、foreachで回しながら一気に処理してしまおうというものです。
ディレクトリ内のファイルのリストを取得する方法については、ファイル名グロブ(glob("*.jpg"))の他に、`ls`を使うという手もあります。
@files = `ls *.jpg`;
余談
UNIXの場合、perlを使わずにコマンドラインからシェルコマンドのforeachを使って処理する方法もあります。$ foreach file (*.jpg) foreach? mv $file $file:s/.jpg/.jpeg/ foreach? end $
既存フィルターの連続使用
上記とは別のアプローチになりますが、コマンドラインから(フィルター名 < なんたら > かんたら)と入力する代りに(引数1 引数2 引数3)で該当ファイルすべてに同じフィルターをかける方法です。
例えばlowercaseを*.htmlにかけて処理し、結果を*.htmとして出力するなら、
この方法だと、ひとつのフィルターが単一処理でも連続処理でも使えるので経済的です。
#! /usr/local/bin/perl
# repfil -- repeat filter --
($fil, $bef, $aft) = @ARGV;
$cmd = "ls *.$bef";
@files = `$cmd`;
foreach (@files) {
/(.*)\.$bef/;
`$fil < $1.$bef > $1.$aft`;
}
これを保存して実行します。$ repfil 引数1 引数2 引数3配列@ARGVから、引数1が$filに、引数2が$befに、引数3が$aftに格納され、$filというフィルターが$befにかけられて、$aftに出力されます。
例えばlowercaseを*.htmlにかけて処理し、結果を*.htmとして出力するなら、
$ repfil lowercase html htmと入力すれば、カレントディレクトリにあるすべてのhtmlファイルのタグが小文字に変換され、同名のhtmファイルとして保存されます。
この方法だと、ひとつのフィルターが単一処理でも連続処理でも使えるので経済的です。
引数のオプション化
例えば処理後のファイル名を指定しない場合やファイル名を指定せずとも動くようにする場合は、引数2と3は始めからプログラムに入れ込んでしまえば簡単です。
更に、よく使用するフィルターを予め変数に用意しておけば、引数1をオプション化して使うことが出来ます。
後は、上で紹介したrenを少し書き換えて実行すれば、_が付けられたファイルを元のファイル名にリネーム出来ます。
更に、よく使用するフィルターを予め変数に用意しておけば、引数1をオプション化して使うことが出来ます。
#! /usr/local/bin/perl
# repfil
($fil, $bef, $aft) = @ARGV;
if($fil eq "-l") {
$filter = "lowercase";
} else {
$filter = $fil;
}
if($bef) {
$cmd = "ls *.$bef";
} else {
$cmd = "ls";
}
@files = `$cmd`;
foreach $files (@files) {
($name, $extention) = split(/\./, $files);
chomp($extention);
unless($aft) {
$aft = "$extention"."_";
}
system("$filter < $name.$extention > $name.$aft");
}
こう書いておけば、repfil -lでlowercaseがディレクトリに対して実行され、元のファイル名の最後に _ が付けられたファイル( hoge.html_ )が出力されます。後は、上で紹介したrenを少し書き換えて実行すれば、_が付けられたファイルを元のファイル名にリネーム出来ます。
#! /usr/local/bin/perl
# ren
@files = glob("*.html_");
foreach $files (@files) {
($name, $extention) = split(/\./, $files);
chomp($extention);
$extention =~ s/html\_/html/ig;
$new = $name.".".$extention;
rename($files, $new);
print "$files renamed to $new\n";
}
ホームページ管理への応用
リンクの貼り替え
各ページから「戻る」リンクの書き換えなどは、すべてのファイルを1発で書き換えてしまうと楽です。
#! /usr/local/bin/perl
# exhref
$match = "index.html";
$write = "top.html";
@_ = <STDIN>;
foreach(@_) {
if(/\<a href([^>]+)\>/) {
s/$match/$write/g;
print;
} else {
print;
}
}
repfilも書き換えます。
#! /usr/local/bin/perl
# repfil
($fil, $bef, $aft) = @ARGV;
if($fil eq "-l") {
$filter = "lowercase";
# --- この下2行を追加 -----------
} elsif($fil eq "-e") {
$filter = "exhref";
# --------------------------------
} else {
$filter = $fil;
}
if($bef) {
$cmd = "ls *.$bef";
} else {
$cmd = "ls";
}
@files = `$cmd`;
foreach $files (@files) {
($name, $extention) = split(/\./, $files);
chomp($extention);
unless($aft) {
$aft = "$extention"."_";
}
system("$filter < $name.$extention > $name.$aft");
}
これで、repfil -eでexhrefが動くようになります。書き換えた後は、ファイル名を元に戻す必要がありますね。
$ repfil cat html_ html $ rm *html_repfilでhtml_をhtmlにコピーしてからrmで消します。
背景や画像の貼り替え
リンクの貼り替えに使ったechrefを使い回ししましょう。
#! /usr/local/bin/perl
# exwp
$match = "kuma.gif";
$write = "buta.gif";
@_ = <STDIN>;
foreach(@_) {
if(/\<body background([^>]+)\>/i) {
s/$match/$write/g;
print;
} else {
print;
}
}
ボタンやアイコンを貼り替えるなら、if文の( )内を/\<img src([^>]+)\>/iに書き換えます。repfilのオプション設定はお好きにどうぞ。
[ CGI Top ]
[ BACK ]
[ Reference Top ]
[ NEXT ]
[ HOME ]