我有一个字符串"ajjjjjjjjjaab"
我想要一个与上一个"ab"
相匹配的模式,而不是整个字符串,甚至是"aab"
。
/a.*?b/ # returns two groups
或
/a.??b/ # matches last aab
都没有效果。
答案 0 :(得分:5)
解决问题的一个简单方法是匹配:
.*(a.*b)
第一个.*
贪婪,它尽可能匹配。然后,您将获得一个捕获的组,其中包含您真正需要的匹配项($1
)。请注意,这假设您匹配模式的最后一次出现。如果您在字符串末尾附近有多个.*(a.*?b)
,并且您希望第一个b
位于最后一个a
之后,则可能需要{{1}}。
答案 1 :(得分:5)
其中一个:
/a[^a]*b/
/a[^ab]*b/
如果a
和b
实际上是更复杂的模式,可以使用以下内容:
/a(?:(?!a).)*b/s
/a(?:(?!a|b).)*b/s
如果a
和b
代表长/复杂模式,则可以避免使用任何其他代码中的变量重复它们。
my $re1 = qr/a/;
my $re2 = qr/b/;
/$re1(?:(?!$re1|$re2).)*$re2/s
也可以使用子模式。
/
(?&A) (?:(?!(?&A)|(?&B)).)* (?&B)
(?(DEFINE)
(?<A> a )
(?<B> b )
)
/xs
答案 2 :(得分:3)
默认情况下,Perl中的模式匹配最左侧,最长*。使用??
,*?
或+?
会将该部分更改为Left Most,Shortest,但Left Most仍然优先。
有一种方法可以让Perl与Right Most相匹配,这可能会让你获得理想的效果,但它也会让下一个人的地狱感到困惑,因此请小心使用它。
基本思想是反转与模式匹配相关的所有内容,因此右边会变为左侧。
my $subject = 'ajjjjjjjjjaab';
my $rev_sub = reverse $subject; # reverse the string being matched.
my $result;
if ($rev_sub =~ /(b.*?a)/) { # reverse the pattern to match.
$result = reverse $1; # reverse the results of the match.
}
print $result;
ikegami和Kobi提供的解决方案都为您的示例找到了类似的结果。根据您的实际模式和字符串,您可能会发现每种方法的性能都有很大差异。始终Benchmark
基于您的实际需求。
*仅对匹配的直接令牌最长,不包括从左到右依次尝试的替换等。
答案 3 :(得分:0)
好的,但是然后只使用/ab/
进行匹配,然后就可以了。或/a{1}b/
。或?