I ♥ WordPress

[時間割:Perl]『ミニマルPerl』その16
2009/01/30 02:12 posted by kunkichi

ちょっと間が空いちゃったけど、木曜日は「Perl」の時間。引き続きfind編です。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 96883
  • パイプの代わりに、バッククォートを使ったコマンド置換で、ファイル名を引数に取るようなところでもPerlは役に立つ。# grep 'John' `ls -d * | perl -wnl -e '-T and print;'カレントにあるディレクトリ・ファイルの一覧(ディレクトリの中身は含まない)からテキストファイルであるものを出力し、それらのうち、’John’を含む行を抽出している。
  • これをファイル形式で書くとこんな感じ#!/usr/bin/perl -s -wnl
     
    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: $_";
    引数 -reで検索したい表現を指定。ファイルがテキストファイルでなければcloseして次のファイル、テキストファイルであれば、引数で指定された表現が含まれているかをチェックして、含まれていればファイル名とその行を表示する。
    こういう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





このページの先頭へ