我的文件包含标记扬声器的会话序列。我的文件格式是:
<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之间有人说话。
我怎样才能得到正确的匹配?
答案 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;