2014-04-05 32 views
0

我有以下信息的XML文件,我計算在XML文件中的停頓中值:如何使用Perl

<Key Time="54288" Type="insert" Value="E" /> 
<Key Time="55288" Type="insert" Value="A" /> 
<Key Time="58298" Type="insert" Value="H" /> 
<Key Time="58398" Type="insert" Value="A" /> 
<Key Time="58498" Type="insert" Value="L" /> 
<Key Time="59298" Type="insert" Value="L" />  
<Key Time="64298" Type="insert" Value="O" /> 

我首先需要計算每個Key項之間的總暫停時間,但只有當暫停(自上次Time以來的時間間隔)等於或高於2400.

爲此我得到了下面的腳本,它也顯示了暫停開始的時間。

perl -nle ' 
    /<Key +Time\s*=\s*"([0-9]+)\s*"/ and push @nums,$1; 
    END{ 
     for(1..$#nums){ 
      $pause=$nums[$_]-$nums[$_-1]; 
      $pause >=2400 ? print "$pause started at ".$nums[$_-1] :() 
     } 
    }' your_file_here > output_file 

此輸出

3010 started at 55288 
5000 started at 59298 

然而,現在我需要提高腳本來檢索以兩種> = 2400-長時間暫停之間的所有值,也包括其中的暫停開始的值。例如,從Time="54288"Time="55288"我有EA;從Time="58298"Time="59298"我有HALL

+0

我不明白這一點。您現有的腳本會找到從A到H以及另一個從L到O的停頓,對不對?所以,如果你的新腳本應該找到包含停止開始和停止停止的信件,你應該得到AHAL,當然? –

+0

順便說一句,爲了理解你的問題,並且容易檢查答案,最好編輯問題並使用獨特的字母! –

+0

@Mark:我想*想要的是'value'屬性*的列表,按時間間隔> = 2400分隔,所以'EA','HALL','O'。至少這就是我的答案!如果是這樣,那麼創建'HALL'的範圍的最終值有一個錯字,應該是'59298'而不是'64298'。我已經解決了這個問題,希望我是對的。 – Borodin

回答

1

這是我認爲你可能想,這是生產的停頓超過40分鐘以上分離Value屬性的列表。

我已經使用了正確的XML解析器模塊XML::Twig來做到這一點。使用正則表達式來解析XML會帶來麻煩。

use strict; 
use warnings; 

use XML::Twig; 

my @nums; 
my $start_time; 
my @blocks = (''); 

my $twig = XML::Twig->new(
    twig_handlers => { Key => \&key_handler } 
); 
$twig->parse(*DATA); 

print "$_\n" for @blocks; 

sub key_handler { 
    my ($twig, $key) = @_; 
    my $time = $key->{att}{Time}; 

    if (defined $start_time) { 
    my $pause = $time - $start_time; 
    push @blocks, ("$pause from $start_time to $time", '') if $pause >= 2400; 
    } 

    $start_time = $time; 
    $blocks[-1] .= $key->{att}{Value}; 
} 

__DATA__ 
<root> 
    <Key Time="54288" Type="insert" Value="E" /> 
    <Key Time="55288" Type="insert" Value="A" /> 
    <Key Time="58298" Type="insert" Value="H" /> 
    <Key Time="58398" Type="insert" Value="A" /> 
    <Key Time="58498" Type="insert" Value="L" /> 
    <Key Time="59298" Type="insert" Value="L" />  
    <Key Time="64298" Type="insert" Value="O" /> 
</root> 

輸出

EA 
3010 from 55288 to 58298 
HALL 
5000 from 59298 to 64298 
O 
+0

這就是我正在尋找的@Borodin。非常感謝。我做了一個單獨的更改,以從XML文件獲取數據,而不是將其包含在腳本文件中[$ twig-> parsefile('myFile.xml');]。但是,我想知道如何能夠同時處理一批XML文件,並根據其原始文件獲得單個文件並提供結果? – ials

+0

@ials:這是一個不同的問題,應該這樣提出。你知道這麼少的編程,你不能在'for(@ARGV){...}'中嵌入這個算法嗎? – Borodin

+0

我是新手,@Borodin ...編程實際上不是我的工作領域,但我有時需要......我會嘗試你的提示(@ARGV)。非常感謝您的幫助。 – ials

0

一個解決方案建模鮑羅廷的,但使用XML::LibXML代替:

use strict; 
use warnings; 

use XML::LibXML; 

my $string = do {local $/; <DATA>}; 

my $dom = XML::LibXML->load_xml(string => $string); 

my @blocks = ''; 

my $lasttime; 
for my $node ($dom->findnodes('//Key')) { 
    my $time = $node->getAttribute('Time'); 

    if (defined $lasttime) { 
     my $pause = $time - $lasttime; 
     push @blocks, "pause from $lasttime to $time", '' if $pause >= 2400; 
    } 
    $blocks[-1] .= $node->getAttribute('Value'); 
    $lasttime = $time; 
} 

print "$_\n" for @blocks; 

__DATA__ 
<root> 
    <Key Time="54288" Type="insert" Value="E" /> 
    <Key Time="55288" Type="insert" Value="A" /> 
    <Key Time="58298" Type="insert" Value="H" /> 
    <Key Time="58398" Type="insert" Value="A" /> 
    <Key Time="58498" Type="insert" Value="L" /> 
    <Key Time="59298" Type="insert" Value="L" />  
    <Key Time="64298" Type="insert" Value="O" /> 
</root>