[時間割:Perl]『ミニマルPerl』その16
2009/01/30 02:12 posted by kunkichi
ちょっと間が空いちゃったけど、木曜日は「Perl」の時間。引き続きfind編です。
ミニマルPerl Unix/LinuxユーザのためのPerl習得法
posted with amazlet at 08.10.06
Tim Maher
オライリージャパン
売り上げランキング: 96883
オライリージャパン
売り上げランキング: 96883
- パイプの代わりに、バッククォートを使ったコマンド置換で、ファイル名を引数に取るようなところでもPerlは役に立つ。
# grep 'John' `ls -d * | perl -wnl -e '-T and print;'カレントにあるディレクトリ・ファイルの一覧(ディレクトリの中身は含まない)からテキストファイルであるものを出力し、それらのうち、’John’を含む行を抽出している。 - これをファイル形式で書くとこんな感じ
#!/usr/bin/perl -s -wnl引数 -reで検索したい表現を指定。ファイルがテキストファイルでなければcloseして次のファイル、テキストファイルであれば、引数で指定された表現が含まれているかをチェックして、含まれていればファイル名とその行を表示する。
BEGIN {
@ARGV and $re or
warin "Usage: grep_text -re='REGEX' filen1 [file2, file3, ・・・]
and exit 255;
-T $ARGV or close ARGV and next;
/${re}/i and print "$ARGV: $_";
こういうcloseの使い方を覚えないとね。 - 最初のコマンドのケースをfindのように再帰的にするならば
# grep 'John' `find . -type f -print | perl -wnl -e '-T and print;' - 引数がファイル名でない場合でも、バリデーションの目的でPerlを使うのも有用。引数のためのプリプロセッサという感じ。
- find で抽出したファイルに対して何かコマンドを実行したい場合は-execを使ったり、
# find . -type f -exec rm {} ¥;とか# find . -type f | xargs rmとかでできるが、それぞれ問題がある。- -execの場合はコマンドのプロセスがfindの抽出結果分だけ起動する。
- xargsの場合は1回のパイプで渡せる上限の数で渡すので、コマンドのプロセスは節約できるが、たとえば以下のケースだと、
# find . -type f | xargs sort | tail -1もしfindの数が1回のパイプの上限を超えていた場合は、分割された「まとまり」単位でsortが実行されるため、全体をsortした結果の最新(最後の1行)にはならなかったりする。
- Perlだとこれを回避できる。以下サンプルスクリプト。
#!/usr/bin/perl -wnlまあプログラミングらしく、最新のタイムスタンプを変数に記録しておいて、それと比較して最も最近のものの情報(ファイル名、タイムスタンプ)を常に更新するような仕組みにすればよいということだね。
BEGIN{ $latest_modified=0; }
$mtime = (stat $_)[9];
if( $mtime > $latest_modified ){
$last_modified = $mtime; ※ここで最新のファイルのタイムスタンプが保持される。
$last_modified_file = $_; ※ここで最新のファイルのファイル名が保持される。
}
END{
print $name;
} - あとxargsだと空白文字を含む引数は別々の引数として処理されしまう。Perlだと空白を区切りとして分割させないこともできる。
# find . -type f | perl -wnl -e 'print -s, " $_";
grepやawkの置き換え、だけでなく、今回のfindのように、組み合わせて有効に使えるというのもPerlのよいところだね
これでfindも終わりました。
次回はこれまでのコマンドよりの部分から、もう少しプログラミングに近いところのお話。







コメント&トラックバック
トラックバックURL: