2011-01-27 90 views
2

我正在尝试编写一个工具,它将查找跨越大型文本文件中多行的空XML标记。例如。不匹配:返回跨多行的正则表达式匹配的行号

<tag> 
ABC 
</tag> 

搭配:

<tag> 
</tag> 

我在写正则表达式匹配多行空格没有问题,但我需要找到这些比赛发生的行号(至少大约)。

我会将我的文本文件分割成一个数组,但是这会非常棘手,因为可能存在大于2行标记/空白的多个数组元素。

任何想法?我的实现需要使用Perl。谢谢!

+1

见http://stackoverflow.com/questions/1732348/regex- match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – Svante 2011-01-27 13:06:09

回答

3

在这类工作中,我宁愿使用xml解析器并输出结束空标记的行号,而不是尝试执行一些繁琐的正则表达式工作。

4
if ($string =~ $regex) { 
    print "Match starting line number: ", 1 + substr($string,0,$-[0]) =~ y/\n//, "\n"; 
} 
0

如果只有一个<tag>每行,你可以使用的特殊车型变量$.包含当前行号。

#!/usr/bin/perl 
use strict; 
use warnings; 
use 5.10.1; 

my ($begin, $tag) = (0, 0, ''); 
while (my $line = <DATA>) { 
    chomp $line; 
    if ($line =~ m#<(tag).*?>#) { 
    $tag = $1; 
    $begin = $.; 
    next; 
    } 
    if ($line =~ m#</($tag).*?>#) { 
    if ($. - $begin < 2) { 
     say "Empty tag '$tag' on lines $begin - $."; 
    } 
    $begin = 0; 
    $tag = ''; 
    } 
} 

__DATA__ 
<tag> 
ABC 
</tag> 

<tag> 
</tag> 

输出:

Empty tag 'tag' on lines 5 - 6 
0

如果你需要一个强大的解决方案,使用真正的XML解析器,而不是天真的模式匹配。

如果你准备用一个脆弱的方法,可能并不总是给出正确的答案,然后 见下文:-)

#!/usr/bin/perl 
use warnings; 
use strict; 

my $xml =<<ENDXML; 
<tag> 
stuff 
</tag> 
<tag> 


</tag> 
<p> 
paragraph 
</p> 
<tag> </tag> 
<tag> 
morestuff 
</tag> 
ENDXML 

while ($xml =~ m#(<tag>\s*</tag>)#g) { 
    my $tag = $1; 

    # use substr() as an "lvalue" to find number of lines before </tag> 
    my $prev_lines = substr($xml, 0, pos($xml)) =~ tr/\n// + 1; 

    # adjust for newlines contained in the matched element itself 
    my $tag_lines = $tag =~ tr/\n//; 

    my $line = $prev_lines - $tag_lines; 
    print "lines $line-$prev_lines\n$tag\n"; 
}