Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何匹配满足正则表达式模式的尽可能短的字符序列?_Regex_Perl_Matching - Fatal编程技术网

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;