我的正则表达式匹配太多。我如何让它停止? [复制]

Posted

技术标签:

【中文标题】我的正则表达式匹配太多。我如何让它停止? [复制]【英文标题】:My regex is matching too much. How do I make it stop? [duplicate] 【发布时间】:2022-01-21 17:43:12 【问题描述】:

我有这个又大又丑的字符串:

J0000000: Transaction A0001401 started on 8/22/2008 9:49:29 AM
J0000010: Project name: E:\foo.pf
J0000011: Job name: MBiek Direct Mail Test
J0000020: Document 1 - Completed successfully

我正在尝试使用正则表达式从中提取片段。在这种情况下,我想抓取 Project Name 之后的所有内容,直到它显示 J0000011: 的部分(11 每次都是不同的数字)。

这是我一直在玩的正则表达式:

Project name:\s+(.*)\s+J[0-9]7:

问题是它直到最后碰到 J0000020: 才会停止。

如何使正则表达式在第一次出现 J[0-9]7 时停止?

【问题讨论】:

项目名称:[^\n]*\n(J[0-9]7) 【参考方案1】:

通过在 .* 后面添加“?”使 .* 不贪婪:

Project name:\s+(.*?)\s+J[0-9]7:

【讨论】:

【参考方案2】:

在这里使用非贪婪量词可能是最好的解决方案,也因为它比贪婪替代方案更有效:贪婪匹配通常会尽可能远(这里,直到文本结尾!)然后回溯一个接一个的字符来尝试匹配后面的部分。

但是,请考虑改用否定字符类:

Project name:\s+(\S*)\s+J[0-9]7:

\S 表示“除了空格之外的所有内容,这正是您想要的。

【讨论】:

如果可以实现,贪婪的负(或正)字符类通常会比惰性量词表现得更好。懒惰要求引擎逐个字符向前跟踪,检查每次遵循的模式,直到匹配;贪婪的字符类可以盲目地重复所需的字符,这可以快得多。因此,您可能会考虑为否定字符类制定更强有力的案例,因为这是贪婪与懒惰的规范。【参考方案3】:

好吧,".*" 是一个贪心选择器。您可以通过使用".*?" 使其不贪婪。当使用后一种构造时,正则表达式引擎将在每一步将文本匹配到"." 中,尝试匹配".*?" 之后的任何内容。这意味着,如果".*?" 之后没有任何内容,则它不会匹配任何内容。

这是我使用的。 s 包含您的原始字符串。此代码是 .NET 特定的,但大多数正则表达式都有类似的内容。

string m = Regex.Match(s, @"Project name: (?<name>.*?) J\d+").Groups["name"].Value;

【讨论】:

【参考方案4】:

我还建议您使用“Expresso”来试验正则表达式 - 它是一个用于正则表达式编辑和测试的出色(免费)实用程序。

它的一个优点是它的 UI 公开了许多不熟悉 regex 的人可能不熟悉的 regex 功能,以方便他们学习这些新概念。

例如,当使用 UI 构建正则表达式并选择“*”时,您可以选中“尽可能少”复选框并查看生成的正则表达式,并测试其行为,即使您以前不熟悉非贪婪的表达方式。

可在他们的网站上下载: http://www.ultrapico.com/Expresso.htm

快速下载: http://www.ultrapico.com/ExpressoDownload.htm

【讨论】:

已经有一些很棒的网站了。我宁愿访问书签也不愿在我的计算机上安装其他程序。【参考方案5】:

(项目名称:\s+[AZ]:(?:\\w+)+.[a-zA-Z]+\s+J[0-9]7)(?=:)

这对你有用。

添加 (?:\\w+)+.[a-zA-Z]+ 将比 .* 更具限制性

【讨论】:

以上是关于我的正则表达式匹配太多。我如何让它停止? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何从python中的正则表达式匹配中返回一个字符串? [复制]

在第一个字符匹配时停止? [复制]

unix:如何判断字符串是否与正则表达式匹配

如何编写匹配非贪婪的正则表达式? [复制]

正则表达式:如何访问一个组的多个匹配项? [复制]

正则表达式 - 在第 n 个空格之间匹配数据并在第 n 个空格处停止