Perl Regex匹配的东西,但要确保匹配字符串不包含字符串

时间:2016-04-16 02:26:57

标签: regex perl

我的文件包含标记扬声器的会话序列。我的文件格式是:

<SPEAKER>John</SPEAKER>
I am John
<SPEAKER>Lisa</SPEAKER>
And I am Lisa

我现在想要确定John说话的每个文档中的第一个序列,然后Lisa说话(然后我想保留文档的整个部分,包括序列)。

我构建了这个正则表达式:

^.*?(<SPEAKER>John<\/SPEAKER>.*?<SPEAKER>Lisa<\/SPEAKER>.*)

但它当然也捕获了一系列发言者是John-Michael-Lisa的案例,即John和Lisa之间有人说话。

我怎样才能得到正确的匹配?

2 个答案:

答案 0 :(得分:1)

这是一个正则表达式,您可以使用它来匹配您描述的内容:

(<SPEAKER>John<\/SPEAKER>(?:(?!<SPEAKER>).)*<SPEAKER>Lisa<\/SPEAKER>.*)

一个小型演示,证明它有效:https://regex101.com/r/iW8vS5/1

然而,正如kchinger和owler所提到的,正则表达式可能不是最好的方法。对于任何长文档,正则表达式解决方案可能比一小段代码慢得多。

答案 1 :(得分:0)

这不是纯粹的正则表达式解决方案,也许其他人可以做到这一点,但我写了一个小循环来检查每一行。如果它找到了你想要的东西,它将保留文件的其余部分。如果它不是完整文档,您需要以正确的顺序提供它。一个正则表达式做你想要的可能会有点慢,因为它会相对复杂,但如果速度很重要,你必须对纯正的正则表达式解决方案进行基准测试(如果有人想出一个)。

编辑注意:?!如果你没有看到它,Lisa是一个负面的预测。在一个正则表达式中,你可能需要使用一些组合的负向前瞻,但祝你好运。稍后阅读它。

open(my $input,"input2.txt")||die "can't open the file";

my $output = "";
my $wanted = 0;
while(<$input>)
{
    $wanted = 1 if(/<SPEAKER>John<\/SPEAKER>/);
    $wanted = 2 if(/<SPEAKER>Lisa<\/SPEAKER>/ && $wanted == 1);
    if(/<SPEAKER>(?!Lisa)/ && /<SPEAKER>(?!John)/ && $wanted == 1)
    {
        $wanted = 0;
        last;
    }
    $output = $output . $_ if($wanted);
}

print "$output" if $wanted;