在行<>

时间:2016-05-24 20:26:06

标签: perl parsing

我在编写日志解析器时遇到问题。我刚开始编写更大的Perl程序/脚本,但是很好地理解bash / ksh,所以我在较小的规模上有一些经验。我为大量的代码道歉,但我不知道我哪里出错了(错误可能会误导,所以我读过)。我已经在这里检查过,PerlMaven和其他一些网站,并且无法让它发挥作用。

我正在尝试将日志文件提供给此解析器,让它按每列拆分日志,并按特定列的实例计数。

在这个解析器中,$statusCode代表一个成功的连接 - 所以我试图计算使用它成功连接的次数 - 以及有数据传输的成功连接数(如由$sentbyClientBytes > 0表示。如果连接成功但发送了0个字节,我只想将一个总和增加一个实例(successconnect++

其他数据暂时可以丢弃,但我会做一些类似于其他一些列的事情 - 只是使用不同的状态代码反复创建相同类型的函数。

先谢谢Perl大师。你们和你们的知识一起举办互联网。

#!/usr/bin/perl
#V0.1 - testing and initiation

use strict;
use warnings;

use Scalar::Util qw(looks_like_number);

my $filename = "/dir/log";

open( my $fh, '<', "/dir/log" ) or die "Cannot open < /root/fall_log";

while ( <$fh> ) {

    # wraps whole process from here to end

    my $sentcount      = 0;
    my $successconnect = 0;

    # define the counts and variables we're using

    my ( $date, $time, $clientIP, $clientPort, $username, $method, $stem,
         $query, $statusCode, $SentByServerBytes, $SentByClientBytes,
         $servername, $serverport ) = split;

    chomp;

    ## (use $line parameter?)

    foreach ( $statusCode ) {  # SC 226 is successful action and usually    
                               # indicates download or login

        if ( $statusCode == "226" ) {

            if ( looks_like_number($SentByClientBytes) ) {

                # adding in looks like number because "-" shows up in the 
                # fields where there are null values

                if ( $SentByClientBytes > 0 ) {
                    $sentcount++ && $successconnect++;
                }
                else {
                    $successconnect++;
                }
            }

            # This function counts each successful established connection and 
            # determines whether bytes were sent - if bytes were sent it 
            # should register as a count of "one" for successful connection 
            # and sent count. These counts should be measured and totaled and 
            # will equal total number of successful downloads and total number 
            # of successful connections. The numbers should be very close to 
            # each other as nearly all successful connections will include a 
            # download.

            print $sentcount & $successconnect;
        }
    }
}

添加我要解析的部分日志(如下)。之后尝试结果的解释:

    2016-03-01 06:16:24 192.168.1.10 - - [5475]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:16:25 192.168.1.10 - USERNAME\admin [5476]quit - - 221 - - - 9045 
2016-03-01 06:26:25 192.168.1.10 - USERNAME\admin [5475]ssh_disconnect timeout - 421 - - - 9045 
2016-03-01 06:26:25 192.168.1.10 - USERNAME\admin [5475]kick - - 421 - - - 9045 
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]ssh_disconnect timeout - 421 - - - 9045 
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]kick - - 421 - - - 9045 
2016-03-01 06:26:26 192.168.1.10 - USERNAME\admin [5475]quit - - 226 - - - 9045 
2016-03-01 06:31:26 192.168.1.10 - - [5516]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:31:27 192.168.1.10 - - [5515]user USERNAME\admin - 226 - - - 9045 
2016-03-01 06:31:28 192.168.1.10 - - [5516]user USERNAME\admin - 226 - - - 9045 
2016-03-01 06:31:28 192.168.1.10 - - [5515]user USERNAME\admin - 226 - - - 9045 
2016-03-01 06:31:28 192.168.1.10 - USERNAME\admin [5516]quit - - 221 - - - 9045 
2016-03-01 06:41:29 192.168.1.10 - USERNAME\admin [5515]ssh_disconnect timeout - 421 - - - 9045 
2016-03-01 06:41:29 192.168.1.10 - USERNAME\admin [5515]kick - - 421 - - - 9045 
2016-03-01 06:41:30 192.168.1.10 - USERNAME\admin [5515]quit - - 221 - - - 9045 
2016-03-01 06:46:30 192.168.1.10 - - [5545]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5544]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5545]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5544]user USERNAME\admin - 331 - - - 9045 
2016-03-01 06:46:32 192.168.1.10 - USERNAME\admin [5545]quit - - 221 - - - 9045 
2016-03-01 06:56:32 192.168.1.10 - USERNAME\admin [5544]ssh_disconnect timeout - 421 - - - 9045 
2016-03-01 06:56:32 192.168.1.10 - USERNAME\admin [5544]kick - - 421 - - - 9045 
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]ssh_disconnect timeout - 421 - - - 9045 
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]kick - - 421 - - - 9045 
2016-03-01 06:56:33 192.168.1.10 - USERNAME\admin [5544]quit - - 221 - - - 9045 
2016-03-01 07:00:01 192.168.1.10 - - [5565]user USERNAME\admin - 331 - - - 9045 
2016-03-01 07:00:02 192.168.1.10 - - [5565]user USERNAME\admin - 331 - - - 9045 
2016-03-01 07:00:03 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/5256570.pdf - 226 - 50935 - 9045 
2016-03-01 07:00:04 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256534.pdf - 226 - 52404 - 9045 
2016-03-01 07:00:05 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256671.pdf - 226 - 50336 - 9045 
2016-03-01 07:00:06 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256565.pdf - 226 - 50858 - 9045 
2016-03-01 07:00:06 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256634.pdf - 226 - 51039 - 9045 
2016-03-01 07:00:07 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/5256536.pdf - 226 - 51657 - 9045 
2016-03-01 07:00:07 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256668.pdf - 226 - 51219 - 9045 
2016-03-01 07:00:08 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256666.pdf - 226 - 50397 - 9045 
2016-03-01 07:00:09 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256641.pdf - 226 - 50652 - 9045 
2016-03-01 07:00:09 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256648.pdf - 226 - 51529 - 9045 
2016-03-01 07:00:10 192.168.1.10 - USERNAME\admin [5565]sent /root/files/otherfiles/75256525.pdf - 226 - 50913 - 9045 
2016-03-01 06:46:30 192.168.1.10 - - [5545]USERNAME\Admin - 226 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5544]USERNAME\Admin -226 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5545]USERNAME\Admin - 331 - - - 9045 
2016-03-01 06:46:31 192.168.1.10 - - [5544]USERNAME\Admin - 331 - - - 9045

这应检查第9列($statuscode)包含226(成功连接)的所有实例,并将其与第10列($SentByServerBytes)进行比较,以查看是否实际发送了数据。如果第10列大于0,则将一个“实例”添加到$successconnect,将一个实例添加到$sentcount。如果($SentByServerBytes)列为零(表示连接成功但未传输任何数据(例如 - 日志文件中的第7,9,10和11行),则将一个实例添加到$successconnect但是不是$sentcount的一个实例。

为了清晰起见重新措辞:

如果$statuscode为226,则始终将一个实例添加到$ successconnect。仅当($SentByServerBytes)大于0时,才将一个实例添加到$sentcount

根据这个日志,我应该结束

$successconnect = 17次成功连接 $sentcount =已发送11个成功文件

我现在是gettig

[root@localhost ~]# ./logcounter1.pl
Use of uninitialized value in string eq at ./logcounter1.pl line 22, <$fh> line 998.
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111[root@localhost ~]

再次感谢大家的帮助!我很难过,但你们总是非常有帮助!!!!!

3 个答案:

答案 0 :(得分:6)

如果您可以提供输入数据样本和所需的输出,那将非常有用。因为它是你的程序中有很多多余的代码

其他人发现的错误并不是真正的问题。 (将foreach与单个值一起使用将只执行一次循环,并且使用与字符串的数字比较将首先将字符串转换为整数。)但它确实表明您对所拥有的内容缺乏了解写入

您正尝试将每行的第九个字段提取为$statusCode的值,以及特定错误

  

在数字eq(==)

中使用未初始化的值

几乎可以肯定,因为日志文件中的一行包含的字段少于9个,因此变量设置为undef

每次从文件中读取一行时,您还会打印$sentcount $successconnect按位和。这是一个非常奇怪的打印值,我想你想在读完整个文件后打印摘要

这是重写你的程序,做我认为你想要的

#!/usr/bin/perl
#V0.1 - testing and initiation

use strict;
use warnings 'all';

use Scalar::Util 'looks_like_number';

my $filename = '/dir/log';

open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!};

my $sent_count      = 0;
my $success_connect = 0;

while ( <$fh> ) {

    my @fields = split;
    next unless @fields >= 9;

    my ( $status_code, $sent_by_client_bytes) = @fields[8,10];

    if ( defined $status_code and $status_code eq '226' ) {

        ++$success_connect;

        if ( defined $sent_by_client_bytes
                and looks_like_number($sent_by_client_bytes)
                and $sent_by_client_bytes > 0 ) {

                ++$sent_count;
        }
    }
}

print qq{\$success_connect = $success_connect\n};
print qq{\$sent_count      = $sent_count\n};

答案 1 :(得分:0)

$statusCode不是数组引用,而是标量字符串,所以做foreach ($statusCode)没有任何意义。

在访问之前,您还应验证$statusCode是否为defined。如果不是,则split的结果不正确,或者您的输入行没有您期望的格式。

一些脚注:

==用于数字,使用eq表示字符串:

if ( $statusCode eq "226") {

if ( $statusCode == 226) {

Perl perlop页面提供了更多信息。

此外,不要依赖$sentcount++ && $successconnect++;等条件的副作用 而是将它作为两个单独的命令:$sentcount++; $successconnect++;

此外,您在第二个;之后错过了$successconnect++。那说,以下......

if ($SentByClientBytes > 0) {           
    $sentcount++ && $successconnect++;
} else {
    $successconnect++
}

应该简化为:

$successconnect++;
if ($SentByClientBytes > 0) { $sentcount++; }

答案 2 :(得分:0)

您的代码:if ( $statusCode == "226" ) {

==用于比较数字,但&#34; 226&#34;是一个字符串,因为你加倍引用它。使用其中一个:

my $procname="SUBROUTINENAME";
if (! defined($statusCode))
    {
    print "$procname ERROR: statusCode not defined\n";
    }
elsif ($statusCode eq "226" ) {...
}

my $procname="SUBROUTINENAME";
if (! defined($statusCode))
    {
    print "$procname ERROR: statusCode not defined\n";
    }
elsif ($statusCode == 226 ) {...
}

我喜欢将过程名称放在错误消息中。 一个常见的错误,朋友。