2009-10-24 29 views
0

我已經開始了一個小寵物的項目來分析日誌文件團隊要塞2日誌文件對每行一個事件,如下列:創建一種日誌文件「組合的」解析器

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 $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將元組的例子如上面將匹配。我認爲,「殺死」事件並不需要完全瞭解玩家,只要它具有創建玩家的信息,這些元組就提供了這些信息。

對不起,如果這是一個漫無目的,但希望你可以提供一些建議!

回答

4

我想我明白你在問什麼。你需要做的是扭轉你的邏輯。首先你需要用正則表達式將字符串分成兩部分,然後提取你的元組。然後你的正則表達式不需要知道這個名字,而你只有兩個通用播放器解析正則表達式。這裏是一個簡短的例子:

#!/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); 

希望這是你在找什麼。

+0

是的,我考慮過這一點,但不確定是否有辦法避免多個步驟。我可以和這個住在一起!我可能會看看其他一些解決方案(比如BNF)來描述日誌條目,但是這肯定會讓我繼續。 謝謝dwp – ocharles 2009-10-24 16:06:47

1

另一種方式來做到這一點,但相同的策略DWP的回答是:

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

你的日誌數據中包含的平衡文本的幾個項目(報價和括號內),所以你可能會考慮Text::Balanced這個工作的一部分,或者可能是一種解析方法,而不是用正則表達式直接攻擊。例如,如果玩家的名字可以包含任意的輸入,後者可能會很脆弱。