Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Perl:我可以使用模式匹配来查找日志文件中的某些行吗_Arrays_Perl_Pattern Matching - Fatal编程技术网

Arrays Perl:我可以使用模式匹配来查找日志文件中的某些行吗

Arrays Perl:我可以使用模式匹配来查找日志文件中的某些行吗,arrays,perl,pattern-matching,Arrays,Perl,Pattern Matching,我有一个包含此类内容的日志文件: 2012年11月19日星期一11:00:01 主机:myserver 累计使用量:629 2012年11月19日星期一12:00:01 主机:myserver 累计使用量:629 使用Perl,我已经了解了如何删除空行并将非空行放入数组中。现在,我正在尝试匹配当前的月份、日期和年份。也就是说,我正在尝试获取所有包含May、21和2013的行(此文件是每天运行24次的脚本的产物。我不需要hh:mm:ss数据 我一直在尝试以以下方式匹配此模式: foreach $

我有一个包含此类内容的日志文件:

2012年11月19日星期一11:00:01
主机:myserver
累计使用量:629
2012年11月19日星期一12:00:01
主机:myserver
累计使用量:629
使用Perl,我已经了解了如何删除空行并将非空行放入数组中。现在,我正在尝试匹配当前的月份、日期和年份。也就是说,我正在尝试获取所有包含
May、21
2013
的行(此文件是每天运行24次的脚本的产物。我不需要
hh:mm:ss
数据

我一直在尝试以以下方式匹配此模式:

foreach $prod (@prod)
{
  # Sun May 19 02:00:01 2013
  if ($prod =~ ((/Sun May 19/) && $prod =~(/2013$/)) )
  {
    print "Howdy! \n"; # just using to indicate success
  }
}  

我可以通过模式匹配来实现这一点,还是应该尝试拆分此项并找到数据匹配项?顺便说一下,一旦找到匹配项,我需要将包含inuse的行放入数组中,并找到当天的最大数。

快速脏regexp:

my @prod = ('Mon Nov 19 11:00:01 2012', 'accurev-ent inuse: 629');
foreach $prod (@prod)
{
  # Sun May 19 02:00:01 2013
  if ($prod =~ /^\w+ (\w+) (\d+) ..:..:.. (\d+)$/)
  {
    print "Hodwy: $3 $1 $2\n";
  }

  if ($prod =~ /inuse: (\d+)$/)
  {
    print "Yo: $1\n";
  }
}  
屈服

Hodwy: 2012 Nov 19
Yo: 629
!/usr/bin/env perl
严格使用;
使用警告;
使用POSIXQW(strftime);
#活动正则表达式查找今天的日期
#注释掉的正则表达式查找当月的日期
#如果您提供合适的时间戳(自纪元起的秒数),
#您可以通过更改来生成任意日期的模式
#时间(函数调用)到$timestamp。
my$pattern=strftime(“%B%d\\d+:\\d+:\\d+%Y”,localtime(time));
#my$pattern=strftime(“%B\\d+\\d+:\\d+:\\d+%Y”,localtime(time));
#打印“$pattern\n”;
我的$regex=qr/$pattern/;
#我的@prod=;
foreach my$prod(@prod)
{
#打印“支票:$prod\n”;
如果($prod=~$regex)
{
打印“$prod\n”;
}
}

这使用
strftime
(来自POSIX)在正确的位置创建当前月份和年份的正则表达式字符串,并处理日期和时间成分所在的数字字符串。然后,它使用
qr/
创建一个带引号的正则表达式,并将其应用于
@prod
数组中的每个条目。如果愿意,可以使
\d+
匹配更加严格;如果r这样做是否值得取决于一个无关匹配的成本。(当前正则表达式的一个版本比它可能的更宽松,承认5月99日和00日,以及2013年5月,等等;它们都允许无效时间通过)。所有这些都可以通过调整正则表达式来解决,而不会对答案产生实质性影响。

你说你需要每天的总数。我来试试。我希望我添加的评论足够。我使用了数组索引,尽管我很确定这可以通过正则表达式的反向引用来完成,但我运气不太好

我想我会纠正我的误读,为什么不呢

open(FILE, "<stackoverflow.data");
my @prod = <FILE>;
close(FILE);

# Strip newlines.
s/\n// for @prod;

my $data; # Hash to store data.


for (my $i = 0; $i < $#prod; $i) {
    my $date  = $prod[$i];                 # First line.
    my $host  = $prod[$i + 1];             # Second line.
    my $inuse = parseInuse($prod[$i + 2]); # Third line.

    $date =~ /^\w+ (\w+) (\d+) .+? (\d+)$/;
    $date = "$1 $2 $3";

    # Initialize inuse value for date.
    if (!defined($data->{$date})) {
        $data->{$date} = 0;
    }

    # Replace stored inuse value if current loop inuse is greater.
    if ($inuse > $data->{$date}) {
        $data->{$date} = $inuse;
    }

    print "Processing $i raw($prod[$i]) sep(date: $date, host: $host, inuse: $inuse) split($inuse)\n";

    # Skip blank line;
    $i += ($prod[$i + 3] =~ m/^\s*?$/) ? 4 : 3;
}

print "\nTotals:\n";
my $matchdate = 'May 19 2013'; # Set to undef to show all.
#$matchdate = undef;

foreach my $date (sort keys %{$data}) {
    if (defined($matchdate) && $date ne $matchdate) {
        next;
    }
    print "$date: $data->{$date}\n";
}


sub parseInuse
{
    my $i = shift;

    my @parts = split(': ', $i);
    $i = @parts[1];
    $i =~ s/\s\+//g;

    return $i;
}



# Mon Nov 19 11:00:01 2012
# Host: myserver
# accurev-ent inuse: 629
# 
# Mon Nov 19 12:00:01 2012
# Host: myserver
# accurev-ent inuse: 800
# 
# Sun May 19 02:00:01 2013
# Host: myserver
# accurev-ent inuse: 629
# 
# Sun May 19 02:00:01 2013
# Host: myserver
# accurev-ent inuse: 1000
open(文件“{$date}\n”;
}
亚帕西努斯
{
我的$i=班次;
my@parts=split(“:”,$i);
$i=@parts[1];
$i=~s/\s\+//g;
返回$i;
}
#2012年11月19日星期一11:00:01
#主机:myserver
#累计使用量:629
# 
#2012年11月19日星期一12:00:01
#主机:myserver
#累计使用量:800
# 
#2013年5月19日星期日02:00:01
#主机:myserver
#累计使用量:629
# 
#2013年5月19日星期日02:00:01
#主机:myserver
#累计使用量:1000

您可以非常轻松地更改过滤范围(例如,对于上午8点到晚上10点之间的最大值,一周内的最大值,等等)通过更改grep中使用的测试。

这似乎是在2012年11月选择日期,而它只应该在2013年5月选择日期……我将查看Date::Manip以获得更可靠的解析日期和比较方法them@qwwqwwq:Good point:是大量日期操作模块之一。就当前用途而言,它们可能是overkill,但提到它们是非常有道理的。有一整段的用于处理,另一段用于,更不用说模块套件了。谢谢你的帮助。只是澄清一下,我不需要每天合计。我需要找到每天的最大数字。啊。抱歉,读错了。你也可以使用哈希来计算,replac用一个值检查进行推送。祝你好运。我想我会修复我的误读。为什么不呢?你应该能够将@JonathonLeffler的日期解析结合起来并让它工作。@jonathon,这有助于我将月份归零,但每次我试图修改日期号的正则表达式时,它都不会给出输出。日期应该是%e,不会。我在想模式应该是-->my$pattern=strftime(“%B%e\\d+:\\d+:\\d+%Y”,localtime(time));但我似乎没有得到。太糟糕了,没有一个血淋淋的额头表情符号(因为撞到墙上)“乔纳森·莱弗勒,我现在明白了。Thanks@jonathonLeffler,当日期从2013年5月31日更改为2013年6月1日时,我遇到了一个问题。显然,我正在处理的日期在一个月的一位数前插入了一个空格。因此,5月31日(Ma(y 3)之间有一个空格)1在日期变为Ju(n)时用两个空格读取1、括号是表示问题区域。比赛直到6月10日才生效,我不能改变我的数据。我好奇的是,是否有一种方法来考虑这种变化,在正则表达式的构造中,仍然匹配正确地发生?放一个<代码> S++/COD>代替代码中的空白> %bs+%d;或者,更准确地说,使用
%B?%d
(其中有两个空格,尽管降价掩盖了这一点;它在月名和日数之间寻找1或2个空格)我无法使这两个选项都起作用。可能部分问题与“scalar localtime()返回的内容有关谢谢你这么快回复我,谢谢你的帮助。
open(FILE, "<stackoverflow.data");
my @prod = <FILE>;
close(FILE);

# Strip newlines.
s/\n// for @prod;

my $data; # Hash to store data.


for (my $i = 0; $i < $#prod; $i) {
    my $date  = $prod[$i];                 # First line.
    my $host  = $prod[$i + 1];             # Second line.
    my $inuse = parseInuse($prod[$i + 2]); # Third line.

    $date =~ /^\w+ (\w+) (\d+) .+? (\d+)$/;
    $date = "$1 $2 $3";

    # Initialize inuse value for date.
    if (!defined($data->{$date})) {
        $data->{$date} = 0;
    }

    # Replace stored inuse value if current loop inuse is greater.
    if ($inuse > $data->{$date}) {
        $data->{$date} = $inuse;
    }

    print "Processing $i raw($prod[$i]) sep(date: $date, host: $host, inuse: $inuse) split($inuse)\n";

    # Skip blank line;
    $i += ($prod[$i + 3] =~ m/^\s*?$/) ? 4 : 3;
}

print "\nTotals:\n";
my $matchdate = 'May 19 2013'; # Set to undef to show all.
#$matchdate = undef;

foreach my $date (sort keys %{$data}) {
    if (defined($matchdate) && $date ne $matchdate) {
        next;
    }
    print "$date: $data->{$date}\n";
}


sub parseInuse
{
    my $i = shift;

    my @parts = split(': ', $i);
    $i = @parts[1];
    $i =~ s/\s\+//g;

    return $i;
}



# Mon Nov 19 11:00:01 2012
# Host: myserver
# accurev-ent inuse: 629
# 
# Mon Nov 19 12:00:01 2012
# Host: myserver
# accurev-ent inuse: 800
# 
# Sun May 19 02:00:01 2013
# Host: myserver
# accurev-ent inuse: 629
# 
# Sun May 19 02:00:01 2013
# Host: myserver
# accurev-ent inuse: 1000
use strict;
use warnings;
use 5.012;

use DateTime::Format::Strptime;
use List::Util qw/max/;

local $/ = "\n\n";
my $parser = DateTime::Format::Strptime->new(
    pattern   => '%a %b %d %H:%M:%S %Y',
    locale    => 'en_US',
    time_zone => 'America/Chicago',
); 
my @records;
for my $record (<DATA>) {
  my ($timestamp, $host, $inuse) = split ("\n", $record);
  $host =~ s/Host: //;
  $inuse =~ s/accurev-ent inuse: //;
  push @records, { timestamp => $parser->parse_datetime($timestamp), 
                   host => $host,
                   inuse => $inuse,
                 };
}

say max map {$_->{inuse}} grep {$_->{timestamp}->ymd() eq '2013-05-21' } @records;

__DATA__
Mon Nov 19 11:00:01 2012
Host: myserver
accurev-ent inuse: 629

Mon Nov 19 12:00:01 2012
Host: myserver
accurev-ent inuse: 629

Sun May 19 02:00:01 2013
Host: myserver
accurev-ent inuse: 629

Tue May 21 02:00:01 2013
Host: myserver
accurev-ent inuse: 1200

Tue May 21 02:00:01 2013
Host: myserver
accurev-ent inuse: 62

Tue May 21 02:00:01 2013
Host: myserver
accurev-ent inuse: 29
1200