代码之家  ›  专栏  ›  技术社区  ›  ocharles

为日志文件创建一种“可组合”分析器

  •  1
  • ocharles  · 技术社区  · 16 年前

    我已经开始了一个小项目来解析团队Fortress2的日志文件。日志文件在每行上都有一个事件,例如:

    L 10/23/2009 - 21:03:43: "Mmm... Cycles!<67><STEAM_0:1:4779289><Red>" killed "monkey<77><STEAM_0:0:20001959><Blue>" with "sniperrifle" (customkill "headshot") (attacker_position "1848 813 94") (victim_position "1483 358 221")
    

    注意,日志文件语法中有一些常见的部分。例如,名称由四部分组成:名称、ID、STEAM ID和当时的玩家团队。我不想重写这种类型的正则表达式,而是希望将其稍微抽象出来。

    例如:

    my $name = qr/(.*)<(\d+)><(.*)><(Red|Blue)>/
    my $kill = qr/"$name" killed "$name"/;
    

    这很好地工作,但是正则表达式现在返回的结果取决于 $name (打破了我试图实现的抽象)。上面的示例将匹配为:

    my ($name_1, $id_1, $steam_1, $team_1, $name_2, $id_2, $steam_2, $team_2)
    

    但我真的在寻找这样的东西:

    my ($player1, $player2)
    

    其中$player1和$player2是以前数据的元组。我认为“被杀”事件不需要确切了解玩家,只要它有创建玩家的信息,这就是这些元组提供的信息。

    对不起,如果这是一个有点闲聊,但希望你能提供一些建议!

    3 回复  |  直到 16 年前
        1
  •  4
  •   dwp    16 年前

    我想我理解你的要求。你需要做的是改变你的逻辑。首先需要regex将字符串分成两部分,然后提取元组。然后,您的regex不需要知道名称,您只需要两个通用的播放器来解析regex。下面是一个简短的例子:

    #!/usr/bin/perl
    
    use strict;
    use Data::Dumper;
    
    my $log = 'L 10/23/2009 - 21:03:43: "Mmm... Cycles!<67><STEAM_0:1:4779289><Red>" killed "monkey<77><STEAM_0:0:20001959><
    Blue>" with "sniperrifle" (customkill "headshot") (attacker_position "1848 813 94") (victim_position "1483 358 221")';
    
    my ($player1_string, $player2_string) = $log =~ m/(".*") killed (".*?")/;
    my @player1 = $player1_string =~ m/(.*)<(\d+)><(.*)><(Red|Blue)>/;
    my @player2 = $player2_string =~ m/(.*)<(\d+)><(.*)><(Red|Blue)>/;
    
    print STDERR Dumper(\@player1, \@player2);
    

    希望这就是你想要的。

        2
  •  1
  •   FMc TLP    16 年前

    另一种方法,但与DWP的答案相同:

    my @players = 
        map { [ /(.*)<(\d+)><(.*)><(Red|Blue)>/ ] }
        $log_text =~ /"([^\"]+)" killed "([^\"]+)"/
    ;
    

    日志数据包含几个平衡文本项(带引号和括号),因此您可以考虑 Text::Balanced 对于这项工作的一部分,或者可能是解析方法,而不是直接使用regex进行攻击。例如,如果玩家名称可以包含任意输入,则后者可能是脆弱的。

        3
  •  1
  •   ysth    16 年前

    考虑写一篇 Regexp::Log 子类。