繁体   English   中英

使用perl中的regex匹配上次出现的事件

[英]Match from last occurrence using regex in perl

我有这样的文字:

hello world /* select a from table_b
*/ some other text with new line cha
racter and there are some blocks of 
/* any string */ select this part on
ly 
////RESULT rest string

文本是多行的,我需要从最后一次出现的“* /”中提取,直到“//// RESULT”。 在这种情况下,结果应该是:

 select this part on
ly 

如何在perl中实现这一目标?

\\\\\\*/(.|\\n)*////RESULT但是从第一个“* /”开始

在这种情况下,一个有用的技巧是在regexp前加上贪婪模式.* ,它会在模式的其余部分匹配之前尝试匹配尽可能多的字符。 所以:

my ($match) = ($string =~ m!^.*\*/(.*?)////RESULT!s);

让我们将这种模式分解为其组成部分:

  • ^.*从字符串的开头开始,并尽可能多地匹配字符。 s修饰符允许.甚至匹配换行符。)字符串开头的锚点^不是绝对必要的,但它确保正则表达式引擎在匹配失败时不会浪费太多时间回溯。

  • \\*/只匹配文字字符串*/

  • (.*?)匹配并捕获任意数量的字符; ? 使它不合适,所以它更喜欢匹配尽可能少的字符,以防有一个以上的位置,其余的正则表达式可以匹配。

  • 最后, ////RESULT只是匹配自己。

由于该模式包含很多斜线,并且因为我想避免倾斜牙签综合症 ,所以我决定使用替代的regexp分隔符。 感叹号( ! )是一种流行的选择,因为它们不会与任何正常的正则表达式语法冲突。


编辑:下面与ikegami的讨论,我想我应该注意,如果你想在更长的正则表达式中使用这个正则表达式作为子模式,并且如果你想保证匹配的字符串(.*?) 永远不会包含////RESULT ,那么你应该将regexp的那些部分包装在一个独立的(?>)子表达式中 ,如下所示:

my $regexp = qr!\*/(?>(.*?)////RESULT)!s;
...
my $match = ($string =~ /^.*$regexp$some_other_regexp/s);

(?>)导致其中的模式失败而不是接受次优匹配(即超出匹配////RESULT的第一个子串的匹配),即使这意味着正则表达式的其余部分将无法匹配。

(?:(?!STRING).)*

匹配任意数量的不包含STRING的字符。 它就像[^a] ,但是对于字符串而不是字符。

如果您知道不会遇到某些输入(如Kenosis和Ilmari Karonen所做的那样),您可以使用快捷方式,但这与您指定的内容相符:

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ ). )* )
    ////RESULT
    (?: (?! \*/ ). )*
    \z
}xs;

如果您不关心*/ ////RESULT之后是否出现*/ ,则以下是最安全的:

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ ). )* )
    ////RESULT
}xs;

如果有两个////RESULT跟随最后一个*/ ,则没有指定会发生什么。 以上匹配直到最后一个。 如果你想匹配到第一个,你可以使用

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ | ////RESULT ). )* )
    ////RESULT
}xs;

这是一个选项:

use strict;
use warnings;

my $string = <<'END';
hello world /* select a from table_b
*/ some other text with new line cha
racter and there are some blocks of 
/* any string */ select this part on
ly 
////RESULT
END

my ($segment) = $string =~ m!\*/([^/]+)////RESULT$!s;

print $segment;

输出:

 select this part on
ly 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM