Regex 如何匹配满足正则表达式模式的尽可能短的字符序列?
我有一个字符串Regex 如何匹配满足正则表达式模式的尽可能短的字符序列?,regex,perl,matching,Regex,Perl,Matching,我有一个字符串“ajjjaab” 我想要一个模式,它将匹配最后一个“ab”,而不是整个字符串,甚至“aab” 或 两者都不起作用。解决问题的简单方法是匹配: .*(a.*b) 由于第一个*是贪婪的,所以它尽可能匹配。然后,您将获得一个捕获的组,其中包含您真正需要的匹配项($1)。请注意,这假设您正在匹配模式的最后一次出现。如果在字符串末尾附近有多个bs,并且希望在最后一个a之后有第一个*(a.*b),则可以选择以下选项之一: /a[^a]*b/ /a[^ab]*b/ 如果a和b实际上是更复
“ajjjaab”
我想要一个模式,它将匹配最后一个“ab”
,而不是整个字符串,甚至“aab”
或
两者都不起作用。解决问题的简单方法是匹配:
.*(a.*b)
由于第一个*
是贪婪的,所以它尽可能匹配。然后,您将获得一个捕获的组,其中包含您真正需要的匹配项($1
)。请注意,这假设您正在匹配模式的最后一次出现。如果在字符串末尾附近有多个b
s,并且希望在最后一个a
之后有第一个*(a.*b)
,则可以选择以下选项之一:
/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
/
(?&A)(?:(?!(?&A)|(?&B))*(?&B)
(?(定义)
(?a)
(?b)
)
/xs
好的,但只需使用/ab/
进行匹配,就可以了。或/a{1}b/
。或者?默认情况下,Perl中的模式匹配是最左、最长的*。使用?
、*?
或+?
将该部分更改为最左侧、最短,但最左侧仍然优先
有一种方法可以让Perl最匹配,这可能会获得您想要的效果,但它也会让下一个阅读您的代码的人感到非常困惑,所以请小心使用它
基本思想是反转与模式匹配相关的所有内容,使右侧变为左侧
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提供的解决方案都为您的示例找到了类似的结果。根据您的实际模式和字符串,您可能会发现每个方法的性能非常不同。总是以你的真实需要为基础
*最长仅用于匹配的立即标记,不包括按从左到右的顺序尝试的替换等。我添加了一个答案,假设您想要最后一个匹配,以及
a
和b
之间的可选字符(即,不是模式ab
)。无论哪种方式,你都可以为这个问题添加很多细节,比如一些例子。这个问题没有任何特定的模式吗?@user-我不知道。Net可以从右向左匹配,也可以始终反转字符串并匹配b.*a
。你也可以尝试类似于a((?!a)。*b
(或a[^a]*b
)的方法,但复杂的模式可能会让它变得混乱-我想你需要的不仅仅是a
和b
…这是特定的模式。注意:a…a…b…b
。虽然这是一个完全正确的答案,这是最小的interesting@user713303事实上,这是唯一正确的答案。您不应该将非贪婪修饰符用作性能提示之外的任何东西。否则,这是一种脆弱且容易出错的黑客行为你是否需要解释这个问题?考虑到上下文,前两个是不言自明的,后两个是前两个的版本,如果a
和b
实际上超过一个字符,则可以使用。我真的很讨厌你需要重复a
(或同时重复a
和b
)两次。后两个正则表达式看起来太复杂了,不适合这样一个简单的正则表达式task@user713303,这是不幸的,但是Required也就是说,如果重复的事情是长而复杂的,变量可以像其他任何地方一样使用。
/
(?&A) (?:(?!(?&A)|(?&B)).)* (?&B)
(?(DEFINE)
(?<A> a )
(?<B> b )
)
/xs
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;