我有这样的文字:
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
修饰符允许.
甚至可以匹配换行符。)字符串开头的 anchor ^
并非绝对必要,但可以确保如果匹配失败,则正则表达式引擎不会浪费太多时间回溯。 \*/
仅与文字字符串*/
匹配。 (.*?)
匹配并捕获任意数量的字符; ?
使它变得不太贪婪,因此,如果有多个位置可以匹配其余的regexp,则它倾向于匹配尽可能少的字符。 ////RESULT
仅与自身匹配。 由于该模式包含许多斜杠,并且由于我想避免使用leaning toothpick syndrome,因此我决定使用替代的regexp分隔符。感叹号(
!
)是一种流行的选择,因为它们不与任何常规的regexp语法冲突。编辑:通过下面与ikegami的讨论,我想我应该注意的是,如果您想将此regexp用作更长的regexp中的子模式,并且要保证
(.*?)
匹配的字符串永远不包含////RESULT
, ,则应将regexp的这些部分包装在independent (?>)
subexpression中,如下所示:my $regexp = qr!\*/(?>(.*?)////RESULT)!s;
...
my $match = ($string =~ /^.*$regexp$some_other_regexp/s);
(?>)
导致其中的模式失败,而不是接受次优匹配(即超出第一个子字符串匹配////RESULT
的子匹配),即使这意味着其余的regexp将不匹配。