Regex Perl—在差异期间忽略某些内容,但在差异之后将其添加回

Regex Perl—在差异期间忽略某些内容,但在差异之后将其添加回,regex,perl,diff,Regex,Perl,Diff,我有两个要区分的文件。第一个文件如下所示: <error line="3" message="message 1"... <error line="4" message="message 2"... <error line="4" message="message 1"... <error line="5" message="message 2"... <error line="5" message="message 3"... <error line="

我有两个要区分的文件。第一个文件如下所示:

<error line="3" message="message 1"...
<error line="4" message="message 2"...
<error line="4" message="message 1"...
<error line="5" message="message 2"...
<error line="5" message="message 3"...
<error line="." message="message 1"...
<error line="." message="message 2"...
<error line="." message="message 1"...
<error line="." message="message 2"...
<error line="." message="message 3"...

这看起来像XML,所以我将继续假设它实际上是XML。如果这不是一个有效的假设,那么。。。这行不通。但不管是谁编写了这些日志文件,都是一个制造假XML的坏人

据我所知,您想从两个文件中提取唯一的“message”属性,并挑出“缺少”的属性吗

像这样的东西就行了

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

my $first = XML::Twig -> new -> parsefile ('samplec.xml');
my $second = XML::Twig -> new -> parsefile ('sampled.xml'); 

foreach my $error ( $second -> get_xpath('//error') ) { 
   my $message = $error -> att('message'); 
   $error -> print unless $first -> get_xpath("//error[\@message=\'$message\']");
}
这仅在消息内容上进行比较—您的示例建议这是唯一的(并在其他结构中的任何位置搜索匹配的消息)。这可能并不完全是你想要的,但类似的技术应该能够做到你想要的

以下更新:

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

my $first = XML::Twig -> new -> parsefile ('samplec.xml');
my $second = XML::Twig -> new -> parsefile ('sampled.xml'); 

my @first_errors = $first -> get_xpath('//error');
my @second_errors = $second -> get_xpath('//error'); 

my $first_err = shift ( @first_errors ); 
my $second_err = shift ( @second_errors );

while ( @first_errors or @second_errors ) { 
   if ( defined $first_err and $first_err -> att('source') eq $second_err -> att('source') ) { 
       ## match
   }
   else {
       #doesn't match, so we print
       $second_err -> print;
       print "\n";

   }     
   $first_err = shift ( @first_errors ); 
   $second_err = shift ( @second_errors ); 
}
我们解析第一个和第二个文件中的XML,并在每次打印时进行迭代。注意-这不是严格意义上的
diff
,因为它假定第一个文件中的错误是第二个文件中错误的子集。(但并非相反)。但它应该只根据“来源”打印新的错误行

通过您的示例数据,它将输出:

<error column="9" line="10" message="Missing a Javadoc comment." severity="warning" source="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck"/>
<error column="35" line="10" message="'{' is not preceded with whitespace." severity="info" source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck"/>
<error column="9" line="14" message="Missing a Javadoc comment." severity="warning" source="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck"/>
<error column="29" line="14" message="'{' is not preceded with whitespace." severity="info" source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck"/>
<error column="21" line="15" message="Variable 'a' should be declared final." severity="info" source="com.puppycrawl.tools.checkstyle.checks.coding.FinalLocalVariableCheck"/>


这看起来像XML。如果是,那么使用解析器就很容易了。但是,如果您能给我们一些有效/完整的XML和预期的输出,那么回答起来会更容易?因为删除行号会丢失数据。把它们放回去是可行的,但是你最好不要这样做,而只是根据消息进行比较。消息在每个文件中都是唯一的吗?不知道它们是怎么回事,因为如果它们是,
diff
将是毫无意义的。看看它-我认为我们有一个-看起来我们试图比较两个文件中的“消息”字段。很抱歉,我的示例不清楚。我已将实际文件添加到问题中。我想找出文件2中新增的错误。但是,如果有人在文件1的开头添加了换行符,那么所有内容都将被视为新错误,即使实际上不会有任何新错误,好吗。我会更新。你的比较标准是什么?只是在XML中排序?是的,没错。一旦我删除了行号,我假设如果错误以相同的顺序出现,那么它们就是存在的错误(因此差异将忽略这些错误)。diff的输出将向我显示任何新引入的错误,但一旦我知道哪些错误是新的,我就想返回行号。谢谢你迄今为止的帮助
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper; 

my $first = XML::Twig -> new -> parsefile ('samplec.xml');
my $second = XML::Twig -> new -> parsefile ('sampled.xml'); 

my @first_errors = $first -> get_xpath('//error');
my @second_errors = $second -> get_xpath('//error'); 

my $first_err = shift ( @first_errors ); 
my $second_err = shift ( @second_errors );

while ( @first_errors or @second_errors ) { 
   if ( defined $first_err and $first_err -> att('source') eq $second_err -> att('source') ) { 
       ## match
   }
   else {
       #doesn't match, so we print
       $second_err -> print;
       print "\n";

   }     
   $first_err = shift ( @first_errors ); 
   $second_err = shift ( @second_errors ); 
}
<error column="9" line="10" message="Missing a Javadoc comment." severity="warning" source="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck"/>
<error column="35" line="10" message="'{' is not preceded with whitespace." severity="info" source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck"/>
<error column="9" line="14" message="Missing a Javadoc comment." severity="warning" source="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck"/>
<error column="29" line="14" message="'{' is not preceded with whitespace." severity="info" source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck"/>
<error column="21" line="15" message="Variable 'a' should be declared final." severity="info" source="com.puppycrawl.tools.checkstyle.checks.coding.FinalLocalVariableCheck"/>