regex - Perl 读取行和下一行

标签 regex xml perl parsing

我需要对 XML 文件进行解析。我需要获取时间代码(开始和结束)以及与该时间相关的句子。

XML 文件是这样的:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Trans SYSTEM "trans-14.dtd">
<Trans scribe="jj" audio_filename="01" version="1" version_date="150211">
 <Episode>
  <Section type="report" startTime="0" endTime="50.28281021118164">
   <Turn startTime="0" endTime="50.28281021118164">
    <Sync time="0"/>

    <Sync time="1.195"/>
    Something
    <Sync time="2.654"/>
    Something 2
    <Sync time="4.356"/>
    Something 3
    <Sync time="9.321"/>
    Something 4
    <Sync time="22.171"/>
    Something 5
    <Sync time="28.351"/>
    Something 6
    <Sync time="35.708"/>
    Something 7
    <Sync time="43.04"/>
    Something 8
   </Turn>
  </Section>
</Episode>

我在 Perl 中尝试过这个,但效果不佳:

#!/usr/bin/perl -nw
next if ! /<Sync/;
$stime = "";
$sentence = "";
$etime = "";

$stime = $1 if (/Sync time="([0-9]+\.[0-9]*)"/);
$sentence = <>;
chomp($sentence);

if ($stime eq ''){ $stime = 0;}

print "$stime  $sentence\n";
__END__

因为我想要的输出格式是:

0  1.195
1.195 2.654 Something
2.654 4.356 Something 2
4.356 9.321 Something 3
9.321 22.171 Something 4
22.171 28.351 Something 5
28.351 35.708 Something 6
35.708 43.04 Something 7
43.04 endTime Something 8

非常感谢

最佳答案

所以首先 - 对 XML 进行面向行的解析确实很糟糕。 XML 是一种数据格式,其结构非常重要 - 因此,有一些东西您可以用完全有效的方式重新构造它,但它会被破坏。

所以你的 10 份开胃菜:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new -> parsefile ( 'sample.xml' );

my $previous_sync = 0; 
foreach my $sync ( $twig -> get_xpath('Episode/Section/Turn/Sync') ) {
   my $sync_time =  $sync -> att('time');
   print "$previous_sync $sync_time ", $sync->text,"\n";
   $previous_sync = $sync_time;
}
print "$previous_sync ", $twig -> get_xpath('Episode/Section',0) -> att('endTime'),"\n";

现在,我遇到了一个小问题,因为您的“Somethings”实际上与相应的“sync”元素没有关联。它们是父级的“文本内容”Turn 。 (Sync 元素是一元标签)。

但是希望这说明了一种更好的解析 XML 的方法吗?

编辑:更新以按原样使用您的文本。 注意:我必须修改您的 XML 以包含 </Trans>作为最后一行,例如:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Trans SYSTEM "trans-14.dtd">
<Trans scribe="jj" audio_filename="01" version="1" version_date="150211">
 <Episode>
  <Section type="report" startTime="0" endTime="50.28281021118164">
   <Turn startTime="0" endTime="50.28281021118164">
    <Sync time="0"/>

    <Sync time="1.195"/>
    Something
    <Sync time="2.654"/>
    Something 2
    <Sync time="4.356"/>
    Something 3
    <Sync time="9.321"/>
    Something 4
    <Sync time="22.171"/>
    Something 5
    <Sync time="28.351"/>
    Something 6
    <Sync time="35.708"/>
    Something 7
    <Sync time="43.04"/>
    Something 8
   </Turn>
  </Section>
</Episode>
</Trans>

因此,如果看起来仍然没问题,并且您实际上并没有尝试使用损坏的 XML,那么这会提供所需的输出。

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $previous_sync;

sub handle_sync {
    my ( $twig, $sync ) = @_;
    my $sync_time = $sync->att('time');
    if ( not defined $previous_sync ) {
        $previous_sync = $sync_time;
        return;
    }
    print "$previous_sync $sync_time ";
    $previous_sync = $sync_time;
    my (@sync_text) = split( "\n", $sync->parent->text );
    pop(@sync_text);    #discard blank line.
    my $line = pop(@sync_text);
    if ( defined $line ) {
        $line =~ s/^\s+//g;
        print $line;
    }
    print "\n";
}

my $twig = XML::Twig->new( twig_handlers => { 'Sync' => \&handle_sync } )
    ->parsefile('sample.xml');
print "$previous_sync ",
    $twig->get_xpath( 'Episode/Section', 0 )->att('endTime'), " ";

my @sync_text =
    split( "\n", $twig->get_xpath( 'Episode/Section/Turn', 0 )->text );
my $line = $sync_text[-2];
$line =~ s/^\s+//g;
print $line, "\n";

这有点捏造,因为其中的“文本”是Turn的一部分。元素 - 所以我采取“打印最后(完整)行”的方法。这似乎可行,但如果您有多行,则可能不会。

关于regex - Perl 读取行和下一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29962466/

相关文章:

regex - 正则表达式 (\S+?) 与 (\S+))

mysql:最好的说法是 "the string up to the first instance of any of the following keywords"?

c# - 逗号破坏分组

java - 与元素类型 "xsi"关联的属性 "xsi:schemaLocation"的前缀 "beans"未绑定(bind)

linux - ftp 下载完成,但解压提示不正确

perl - 如何输出用引号括起来的每个 Perl 数组元素?

.net - 正则表达式帮助,解析为 NameValueCollection

android - 是否可以在两个 strings.xml 文件之间进行选择?

python - 使用scrapy从html源中删除不必要的标签内容

mysql - DBI 下批量事务 DELETE 导致 InnoDB 锁耗尽