如果找到单词,如何停止正则表达式匹配?

时间:2017-08-18 01:53:53

标签: php regex perl

我有这样的文字:

TEXT 786
OPQ RTS

APPENDIX A 

TITLE 

TEXT 123 
ABC EFG 

APPENDIX B

TEXT 456
HIJ KLM

TEXT 786
OPQ RTS

APPENDIX A 

TITLE 

TEXT 123 
ABC EFG 

TEXT 456
HIJ KLM

我尝试使用正则表达式提取从APPENDIX AAPPENDIX B的所有文本,如果APPENDIX B存在,否则从APPENDIX A到结束(即,HIJ KLM)。此外,APPENDIX A必须出现在TITLE之前的15个字之内。这就是我到目前为止所提出的:

(\b(?:appendix)(?:.){0,15}(?:title)(?:.*)(?:appendix){0,1})/is

问题是,如果APPENDIX B存在,捕获不会停留在APPENDIX B,它会一直捕获到最后。

3 个答案:

答案 0 :(得分:1)

一种方法是对可选部分使用交替

perl -0777 -wlnE'
    @m = /(appendix .{0,15} title (?: .*?appendix\s\w+ | .*) )/xsig; 
    say for @m
' input.txt

/g,以匹配appendix个标记中的所有部分。

或者使用多个组进行捕获,一个用于可选项目,然后对其进行测试并相应地使用

perl -0777 -wne'
    @m = /(appendix .{0,15} title) (.*? appendix\s\w+)? (.*)/xsi;
    print join "", ($m[1] ? @m[0,1] : @m[0,2])
' input.txt

这是有效的,因为$2 是为第二个(创建的,即使没有匹配也是如此。

使用更多捕获组,您可以在第二种情况下过滤? grep { defined } @m。如果可能有多个appendix - 部分在此方法中更好地使用while$N个变量

while (/(appendix.{0,15}title)(.*?appendix\s\w+)?(.*)/sig) {
    my $appx_section = ($2) ? $1.$2 : $1.$3;
    ...
}

因为所有捕获的一个大@m需要一点点分析。

所有这些都会在两种情况下打印所需的输出,包括多个appendix - 部分。

我已将其包装在单行中进行准备测试。代码在Perl脚本中工作。

答案 1 :(得分:0)

this为灵感。 基本上,我通过换行符拆分文本,然后在每一行上迭代并将其转换为块。

这些块就是你想要的。 :

我不熟悉perl,但这个想法应该是一样的。

答案 2 :(得分:0)

就像这样,$ var是你的字符串。

if ( $var=~m#(APPENDIX A.{0,15}TITLE.*?(?:APPENDIX B|$))#s )
{
    print $1."\n";
}
else 
{

    print "failed\n";
}

你的问题是这个"(?:。)(?:附录){0,1})"贪婪的匹配加上{0,1},这意味着它总是会占用很多,因为正则表达式是贪婪的。 ?是非贪婪的,例如,只需尽可能少地进行比赛