【问题标题】:Simple Perl Regex parser简单的 Perl 正则表达式解析器
【发布时间】:2011-04-11 12:03:42
【问题描述】:

嘿,我正在开发一个非常基本的解析器。我几乎可以肯定我的正则表达式是正确的,但值似乎没有存储在我的$1$2 中。难道我做错了什么?我只是在寻找改变我的代码的提示。感谢您的任何建议!另外,我是 Perl 的新手,所以如果我做错了什么,我希望能站稳脚跟,养成良好的习惯。

文件中的示例行:

Sat 02-August-2008 20:47 - 123.112.3.209 - "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;

我只是从时代中得到时间。

foreach my $line (@lines)
{   
my $match =~ /\d\d-\w+-\d{4} (\d)(\d):\d\d/;

if( $1 == 0)
{
    $times[$2] = $times[$2] + 1;
}
else
{   
    my $time = $1.$2;
    $times[$time] = $times[$time]+ 1;
}
 }


print "\n";
for(my $i=0;$i<24;$i++)
{
print "$i: $times[$i]\n";
}

【问题讨论】:

  • 你要解析什么?你知道,我们在这里不是通灵者。
  • @jesperE 编辑示例。
  • 我知道我正在从文件中获取这些行。我之前测试过,并且能够重新打印循环中的每一行。

标签: regex perl parsing


【解决方案1】:

如果你想匹配 $line 不应该读取代码

$line =~ /\d\d-\w+-\d{4} (\d)(\d):\d\d/;

See here.

【讨论】:

  • 嗯,我进行了更改,但仍然无法正常工作。我的 1 美元和 2 美元似乎是空的。我很欣赏这个提示,我认为你可能对它必须是 $line 是正确的,但由于我充其量是 Perl 的初学者,我不确定
  • 正如预期的那样,我从示例行中得到 2 和 0。你确实在$line前面去掉了my,对吧?
  • 哈哈,谢谢你看透了我的新鲜感。感谢您抽出宝贵时间提供帮助。度过一个愉快的夜晚。
【解决方案2】:

你能举一些例子来说明你试图匹配什么样的模式?否则我将无法判断您的正则表达式是否与您的模式匹配。但是,您可以对代码进行一些改进:

首先,如果要使用 $1、$2 等,请始终测试匹配是否成功

if($match =~ /\d\d-\w+-\d{4} (\d)(\d):\d\d/) {

    if( $1 == 0)
    {
        $times[$2] = $times[$2] + 1;
    }
    else
    {   
        my $time = $1.$2;
        $times[$time] = $times[$time]+ 1;
    }
} else {
    warn "no match!\n";
}

其次,始终使用“-w”开关。在这种情况下,您可能会收到关于 $1 和 $2 由于匹配失败而未初始化的警告消息:

#!/usr/bin/perl -w

【讨论】:

  • 感谢您的提示。对此,我真的非常感激。其他人的回答解决了我的问题,所以没有必要更详细地研究我的问题。但是,我会将您的提示合并到我的代码中。度过一个愉快的夜晚
【解决方案3】:

首先,如果您是 Perl 的新手,CPAN 的优势之一就是那里有许多解决方案。不要重新发明轮子!

有一个很棒的模块Date::Parse 可以为你解析时间部分。然后,您遇到的唯一正则表达式问题是将行的时间部分分开。

根据您的单行示例,此代码将执行此操作:

use strict;
use warnings;

use Date::Parse;

my $line="Sat 02-August-2008 20:47 - 123.112.3.209 - \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;";
my $tmpart;

if ($line=~ /^(.*\d+:\d+) -/) {
    $tmpart=$1;

    print "Time part = $tmpart\n";

    my $time=str2time($tmpart);
    my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($tmpart);

    $year+=1900;
    $month+=1;

    print "Unix time: $time\n";
    print "Parsed time: $month/$day/$year $hh:$mm:$ss  \n\n";
} 
else {
   warn "no match!\n";
}   

这将返回一个易于使用的 Unix 时间数字。或者(如图所示)您可以解析时间的各个组成部分。

【讨论】:

  • 这一行会产生一些问题:my $tmpart = $1 if $line=~ /^(.*\d+:\d+) -/; 如果你的正则表达式不匹配,$tmpart 是未定义的,你会得到一堆警告和虚假结果。
  • 通过一些错误逻辑代码轻松修复。完毕!感谢您指出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多