perl 分析mysql日志[追加询问]

perl 分析mysql日志[追加询问]

元旦快乐~~~~~~~~~~~!

1. 我想分析出来 Query_time: 为 1 秒时, 执行的sql 语句

2. mysql的日志文件 s.log 内容及格式如下:


# Query_time: 0  Lock_time: 0  Rows_sent: 1  Rows_examined: 2
SELECT template
FROM mos_templates_menu
WHERE client_id='0' AND menuid='0';

# Query_time: 0  Lock_time: 0  Rows_sent: 0  Rows_examined: 0
DELETE FROM mos_session
WHERE (time < 1198124076);

# Query_time: 0  Lock_time: 0  Rows_sent: 1  Rows_examined: 285
SELECT count(*) FROM mos_stats_agents
WHERE agent='Mozilla 5.0' AND type='0';

# Query_time: 0  Lock_time: 0  Rows_sent: 0  Rows_examined: 0
UPDATE mos_stats_agents SET hits=(hits+1) WHERE agent='Mozilla 5.0' AND type='0';

# Query_time: 0  Lock_time: 0  Rows_sent: 1  Rows_examined: 285
SELECT count(*) FROM mos_stats_agents
WHERE agent='Unknown' AND type='1';

# Query_time: 0  Lock_time: 0  Rows_sent: 0  Rows_examined: 0
UPDATE mos_stats_agents SET hits=(hits+1) WHERE agent='Unknown' AND type='1';


# Query_time: 1  Lock_time: 0  Rows_sent: 1  Rows_examined: 285
SELECT count(*) FROM mos_stats_agents WHERE agent='com' AND type='2';


3.  perl 代码如下:

[Copy to clipboard] [ - ]
CODE:
#!/usr/bin/perl

use strict;

##########日志文件路径
my $filepath = '/tmp/s.log';

open FP, $filepath;

foreach(<FP>) {

# 以"# Query" 为标识符, 划分为有两个下标的数组,
# $items[0] 为sql 语句, $items[1] 为# Query的那行.

        my @items = split(/# Query/,$_);

#匹配出 Query_time: 1 的行, 并打印出执行的sql语句

        if(my @r = grep (/ime: 1/,$items[1])) {
                print "@r\n$items[0]";
        }
}

close(FP);

4.  输出的结果,不是预期的结果.
只把 Query_time: 1 的行打印出来了.
而相对应的 $items[0]  没有打印出来.

解答:

perl -0 -ne 'print $& while(/# Query_time: 1[^;]*;\s*/mig);' s.log
perl -ne '$/="";print if /Query_time: 1/' s.log

-----------------------------------------------------------------------------------------------------

新问题:

open FP, $filepath;
undef $/;

while (<FP>) {
        if(@_ =/Query_time: (\d+)  Lock_time: (\d+)  Rows_sent: (\d+)  Rows_examined: (\d+)([^;]*;\s*)/mig) {
                my @s = join("\n",@_);
                                print "@s\n"     #打印出所有的内容, 却不能控制里面的内容输出.
                print "\n$1\t$2\t$3\t$4\t$5\n";  #仅仅打印出来相同的内容,最后一次的赋值结果.不像@s 输出所有的内容.      我想对 $1 进行操作, 如:
                               if($1 == 1) {
                                      print "$5\n";
                               }   
        }
}

再次劳驾一下各位, 谢谢~!

perl -ne '$/="";print if /Query_time: 1/' s.log


[Copy to clipboard] [ - ]
CODE:
perl -0 -ne 'print $& while(/# Query_time: 1[^;]*;\s*/mig);' s.log

谢谢两位.

但是我写程序的时候, 却不能正确打印出来.

my $filepath = '/tmp/s.log';

open FP, $filepath;

my @items = <FP>;

if(@items =~/# Query_time: 1[^;]*;\s*/mig) {
                print "$items[0]\n";
}

希望能再指点一下. 非常感谢.
my @items=<FP>;

if(@items....

这里改成:
undef $/;

while(<FP>){
   ...
}
再次感谢 __lxmxn__  
已经搞定.

学了不少perl的技巧. thanks.
open FP, $filepath;
undef $/;

while (<FP>) {
        if(@_ =/Query_time: (\d+)  Lock_time: (\d+)  Rows_sent: (\d+)  Rows_examined: (\d+)([^;]*;\s*)/mig) {
                my @s = join("\n",@_);
                                print "@s\n"     #打印出所有的内容, 却不能控制里面的内容输出.
                print "\n$1\t$2\t$3\t$4\t$5\n";  #仅仅打印出来相同的内容,最后一次的赋值结果.不像@s 输出所有的内容.      我想对 $1 进行操作, 如:
                               if($1 == 1) {
                                      print "$5\n";
                               }   
        }
}

再次劳驾一下各位, 谢谢~!

除了2楼的方法,其他写法我看的很晕
你7楼的写法,我调来调去也没搞懂……

而2楼的写法,在$/ undef的情况下,莫非还能识别空行?这点我没懂

我自己写了个我觉得看起来清晰些的,你可以参考:

[Copy to clipboard] [ - ]
CODE:
use strict;        use warnings;
my $filepath = "s.log";
open (FP, $filepath);
my $flag=0;
my $sql="";
while(<FP>){
        if(/Query_time: 1/){$flag = 1;        $_=<FP>};
        $sql .= $_ if $flag == 1;
        if(/;/){
                print $sql if $sql;
                $flag=0;        $sql="";
        };
}

if确实太多了……,你想想办法可不可以改


QUOTE:
原帖由 perljoker 于 2008-1-4 10:38 发表

除了2楼的方法,其他写法我看的很晕
你7楼的写法,我调来调去也没搞懂……

而2楼的写法,在$/ undef的情况下,莫非还能识别空行?这点我没懂

我自己写了个我觉得看起来清晰些的,你可以参考:
...

undef $/

$/=""
是不同的,第二个$/是定义了的,第一个是没定义的。
$/=""会以空行,甚至是连续的空行为分隔。


QUOTE:
原帖由 ly5066113 于 2008-1-4 11:01 发表


undef $/

$/=""
是不同的,第二个$/是定义了的,第一个是没定义的。
$/=""会以空行,甚至是连续的空行为分隔。

谢谢,学习了,以前还没注意到这个东西