如何在Perl中的起始和结束正则表达式之间提取行

时间:2016-06-24 10:54:18

标签: regex perl

我想使用Perl循环遍历文件(或数组),在匹配正则表达式时启动处理元素,并在满足另一个正则表达式时停止处理。

一种方法是将一个变量用作标志(满足启动正则表达式时= 1,满足结束正则表达式时= 0)。

例如,以下作品但非常难看!!

use strict;

my @file = (
    "<title>List of widgets</title>\n",
    "<widgets>\n",
    "   <button>widget001.xml</button>\n",
    "   <textArea>widget002.xml</textArea>\n",
    "   <menu>widget002.xml</menu>\n",
    "</widgets>\n",
    "<footer>\n",
    "   This is the footer\n",
    "</footer>\n",
);

my $in_list_widgets = 0;
for my $line (@file) {
    if ($line=~m%<widgets%) {
        $in_list_widgets = 1;
    } elsif ($line=~m%</widgets>%) {
        $in_list_widgets = 0;
    } else {
        if ($in_list_widgets == 1) {
            &process_line($line);
        } else {
            #Do nothing
        }
    }
}

sub process_line {
    my $line = shift;
    print $line;
}

什么是更优雅的方式,并仍然得到相同的结果?

<button>widget001.xml</button>
<textArea>widget002.xml</textArea>
<menu>widget002.xml</menu>

由于

2 个答案:

答案 0 :(得分:1)

关于这是XML - 它看起来像是 - 我建议使用XML解析器。

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig -> parse ( \*DATA );
$twig -> set_pretty_print('indented');

$_ -> print for map { $twig -> findnodes("//$_",0) } qw ( button textArea menu );

__DATA__
<root>
  <title>List of widgets</title>
  <widgets>
    <button>widget001.xml</button>
    <textArea>widget002.xml</textArea>
    <menu>widget002.xml</menu>
  </widgets>
  <footer>
   This is the footer
</footer>
</root>

输出:

<button>widget001.xml</button>
<textArea>widget002.xml</textArea>
<menu>widget002.xml</menu>

或者为了清楚起见:

my $twig = XML::Twig -> new -> parsefile('your_file'); 
foreach my $widgets ( $twig -> root -> children('widgets') ) {
   foreach my $child ( $widgets -> children ) { 
      $child -> print;
      print "\n";
   }
}

答案 1 :(得分:0)

您可以使用如下语法<match_regex_1> .. <match_regex_2>

use strict;

my @file = (
    "<title>List of widgets</title>\n",
    "<widgets>\n",
    "   <button>widget001.xml</button>\n",
    "   <textArea>widget002.xml</textArea>\n",
    "   <menu>widget002.xml</menu>\n",
    "</widgets>\n",
    "<footer>\n",
    "   This is the footer\n",
    "</footer>\n",
);

my $in_list_widgets = 0;
for my $line (@file) {
    if ($line=~m%<widgets% .. $line=~m%</widgets>%) {
        &process_line($line) if ($line!~m%<(widgets|/widgets>)%);
    } else {
        #Do nothing
    }
}

sub process_line {
    my $line = shift;
    print $line;
}

一些解释:

  • if ($line=~m%<widgets% .. $line=~m%</widgets>%):当第一个条件为真时开始执行以下块,直到最后一个条件为真。
  • &process_line($line) if ($line!~m%<(widgets|/widgets>)%);:如果没有if ($line!~m%...,行<widgets></widgets>也会被处理

希望它可以提供帮助。