2014-04-05 27 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>