正则表达式在第一场比赛时停止

pub*_*avi 489 regex

我的正则表达式看起来像

<xxxx location="file path/level1/level2" xxxx some="xxx">
Run Code Online (Sandbox Code Playgroud)

我只对分配给位置的报价部分感兴趣.如果没有贪婪的开关,它不应该像下面那么容易吗?

/.*location="(.*)".*/
Run Code Online (Sandbox Code Playgroud)

似乎没有用.

Dan*_*uis 1001

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

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

/location="(.*?)"/
Run Code Online (Sandbox Code Playgroud)

添加一个?量词(?,*+)会使它变得非贪婪.

  • 谢谢Daniel.**"在量词上添加?(?,*或+)会使它变得非贪婪."**对我来说是有用的提示. (42认同)
  • FWIW,因为你使用VIM,这个正则表达式需要有点不同:而不是`.*?`它是`.\ { - }`用于非贪婪的匹配. (28认同)
  • 的?描述了我试图解决这个问题的困惑.多么合适. (10认同)

sep*_*p2k 48

location="(.*)"除非你让它变得非贪婪location=,some="xxx否则将从"之后直到" 匹配.所以,你要么需要.*?(即使它非贪婪)或更好的替换.*[^"]*.

  • +1,`[^"]*"`比`.*?"更清楚."`任何一天 (7认同)
  • 对于大多数正则表达式引擎,[^"]*也可能更快,因为它不需要在当前模式之后查找模式. (3认同)
  • @Kip:你可能是对的,但是 `.*?` 符号比 `[^"]*` 更通用 (2认同)

小智 29

怎么样

.*location="([^"]*)".*
Run Code Online (Sandbox Code Playgroud)

这样可以避免使用.*进行无限制搜索,并且与第一个引号完全匹配.

  • 由于 [grep 中的差异](/sf/ask/1641792071/),如果考虑可移植性,上述应该是首选模式。 (2认同)

cod*_*eim 18

如果您的引擎支持,请使用非贪婪匹配.加?在捕获内部.

/location="(.*?)"/
Run Code Online (Sandbox Code Playgroud)


Udd*_*tam 8

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

例如,

在此输入图像描述

如果你有全局标志/g,它将匹配所有最低长度匹配,如下所示. 在此输入图像描述


tri*_*eee 5

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

如果您的停止条件是单个字符,那么解决方案很简单;代替

a(.*?)b
Run Code Online (Sandbox Code Playgroud)

你可以匹配

a[^ab]*b
Run Code Online (Sandbox Code Playgroud)

即指定不包括开始和结束分隔符的字符类。

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

start(|[^e]|e(|[^n]|n(|[^d])))end
Run Code Online (Sandbox Code Playgroud)

捕获start和 第一次出现之间的匹配end。请注意带有嵌套括号的子表达式如何拼出许多替代项,这些替代项之间e仅当后面没有跟随等等时才允许nd,并且还要注意覆盖空字符串作为一种替代项,该替代项与不允许的内容不匹配那个特定的点。

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