実用perl正規表現1 #perl

ログの加工をしたくなることが多くなってきたので、perlの実用的に使える正規表現をメモっておく。
今回、下記のログ抜粋から、「QUEUE(xxx)」「CLUSQMGR(xxx)」「CLWLRANK(xxx)」「PUT(xxx)」のxxxを抽出する。
※同じ内容のログが繰り返されることを前提してます。

ログの抜粋

     1 : dis qc(QLC01.RQMGR03)
AMQxxxx: キューの内容を表示します。
   QUEUE(QLC01.RQMGR03)                    TYPE(QCLUSTER)
   ALTDATE(2012-12-16)                     ALTTIME(20.11.52)
   CLUSDATE(2012-12-16)                    CLUSTER(GALAXY)
   CLUSQMGR(RQMGR03)                       CLUSQT(QLOCAL)
   CLUSTIME(20.23.13)                      CLWLPRTY(0)
   CLWLRANK(0)                             DEFBIND(OPEN)
   DEFPRTY(0)                              DEFPSIST(NO)
   DEFPRESP(SYNC)                          DESCR( )
   PUT(ENABLED)                            QMID(RQMGR03_2012-12-16_20.11.48)
MQSC コマンドを 1 つ読み取りました。
構文エラーがあるコマンドはありません。
有効な MQSC コマンドはすべて処理されました。

log_parse.pl

#!/usr/bin/perl
use strict;
use warnings;

my $file = shift die "USAGE: $0 [FILE]" unless $file;

open my $fh, "<", $file or die qq/Cant open file "$file": $!/;

my $ptn_clusqmgr = qr/(.+CLUSQMGR\()(.+)(\)\s)/x;
my $ptn_queue = qr/(.+QUEUE\()(.+)(\)\s)/x;
my $ptn_put = qr/(.+PUT\()(.+)(\)\s)/x;
my $ptn_rank = qr/(.+CLWLRANK\()(.+)(\)\s)/x;

print "queue clusqmgr clwlrank put\n";
while (my $line = <$fh>) {
        chomp $line;
        if ($line=~/$ptn_queue/) {
                print $2." ";
        } elsif ($line=~/$ptn_clusqmgr/) {
                print $2." ";
        } elsif ($line=~/$ptn_rank/) {
                print $2." ";
        } elsif ($line=~/$ptn_put/) {
                print $2."\n";
        }
}
close $fh;

実行結果

$perl log_parse.pl log
queue clusqmgr clwlrank put
QLC01.RQMGR03 RQMGR03 0 ENABLED
$

ざっくり、
引数チェック⇒ファイルオープン⇒正規表現宣言⇒ファイル読み込み処理⇒マッチした文字列を標準出力⇒ファイルクローズ
といった処理になっています。

my $file = shift die "USAGE: $0 [FILE]" unless $file;

引数がなかった場合、エラーを出力しexitします。

open my $fh, "<", $file or die qq/Cant open file "$file": $!/;

ファイルをオープンし、失敗した場合エラーを出力しexitします。

qr/(.+CLUSQMGR\()(.+)(\)\s)/x;

正規表現は、以下のような処理をしています。

  • "qr//" 正規表現クォート。正規表現としてコンパイルして結果を変数に代入することのできる形式へと変換します
  • "()" 括弧でくくることでマッチした部分を$1,$2,$3...と格納してくれます。
  • ".+" "."は改行以外の文字列、"+"は前の正規表現が1個以上続いていることを表しています。
  • "\(" 括弧は"\"でエスケープする必要があります。

close $fh;

そして最後は、ファイルハンドラの解消処理。

最後に

文字列抜き出し処理をSHELLで書いても汚いコードになると思ったらperlで書くのはお勧め。
perlならすっきり、そして手軽。