在第一次匹配时停止的正则表达式

我的正则表达式模式看起来像

<xxxx location="file path/level1/level2" xxxx some="xxx">

我只对分配给位置的引号中的部分感兴趣。不应该像下面这样简单而没有贪婪的开关吗?

/.*location="(.*)".*/

似乎不工作。

933254 次浏览

您需要使正则表达式懒惰/不贪婪,因为默认情况下,"(.*)"将匹配所有"file path/level1/level2" xxx some="xxx"

相反,你可以让你的点星不贪婪,这将使它匹配尽可能少的字符:

/location="(.*?)"/

在量词(?*+)上添加?使其不贪婪。

注意:这仅适用于实现Perl 5扩展的正则表达式引擎(Java、Ruby、Python等),但不适用于“传统”正则表达式引擎(包括Awk、sedgrep但不包括-P等)。

如果您的引擎支持,请使用非贪婪匹配。在捕获中添加?

/location="(.*?)"/

location="(.*)"将从location=之后的"匹配到some="xxx之后的",除非您使其非贪婪。

所以你要么需要.*?(即通过添加?使其不贪婪),要么更好地将.*替换为[^"]*

  • [^"]匹配除“<引号-标记>之外的任何字符
  • 更通用:[^abc]-匹配除a、b或c之外的任何字符

怎么样

.*location="([^"]*)".*

这避免了使用.*进行无限搜索,并将与第一个引号完全匹配。

使用没有全局标志的Lazy量词?就是答案。

Eg,

在此处输入图片描述

如果您有全局标志/g,那么它将匹配所有最低长度的匹配,如下所示。 输入图片描述

因为您正在使用量化子模式并且如perldoc中所述,

默认情况下,量化的子模式是“贪婪”,也就是说,它将 尽可能匹配很多次(给定特定的起始位置) -同时还能让图案的其余部分吻合-如果你想要的话 以匹配最小次数可能,跟随量词 "?" . 注意,含义不会改变,只是 “贪吃”:

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

因此,为了允许您的量化模式进行最小匹配,请遵循?

/location="(.*?)"/

这是另一种方法。

这是你想要的。这是懒惰的[\s\S]*?

<强>第一项: [\s\S]*?(?:location="[^"]*")[\s\S]*替换为:$1

解释说明https://regex101.com/r/ZcqcUm/2


为了完整性,这是最后一个。这是贪婪的[\s\S]*

最后一项:[\s\S]*(?:location="([^"]*)")[\s\S]* 替换为:$1

解释说明https://regex101.com/r/LXSPDp/3


这两个正则表达式之间只有一个区别,那就是?

这里的其他答案未能为不支持非贪婪匹配的正则表达式版本提供完整的解决方案。贪婪量词(.*?.+?等)是Perl 5扩展,传统正则表达式不支持。

如果您的停止条件是单个字符,则解决方案很容易;而不是

a(.*?)b

你可以匹配

a[^ab]*b

即指定一个排除起始分隔符和结束分隔符的字符类。

在更一般的情况下,您可以精心构造一个表达式,例如

start(|[^e]|e(|[^n]|n(|[^d])))end

捕获startend第一次出现之间的匹配。请注意,带有嵌套括号的子表达式如何拼出许多替代方案,这些替代方案之间只有在e后面没有nd等等的情况下才允许e,并且还要注意将空字符串作为一个替代方案覆盖,该替代方案不匹配在该特定点不允许的任何内容。

当然,在大多数情况下,正确的方法是为您尝试解析的格式使用适当的解析器,但有时,可能没有可用的解析器,或者您使用的专用工具坚持使用正则表达式而不是其他。

import regex
text = 'ask her to call Mary back when she comes back'
p = r'(?i)(?s)call(.*?)back'
for match in regex.finditer(p, str(text)):
print (match.group(1))

输出: 玛丽