为啥这个正则表达式在最后一场比赛中有空格?

Posted

技术标签:

【中文标题】为啥这个正则表达式在最后一场比赛中有空格?【英文标题】:Why does this regex space in the last match?为什么这个正则表达式在最后一场比赛中有空格? 【发布时间】:2016-05-16 12:15:49 【问题描述】:

我有以下文字:

2 HCl + 12 Na + 3 (Na₃Cl₂)₂₄ → 2 NaCl + H₂

我想匹配每个分子,包括它的系数。下面的正则表达式几乎可以工作,但是在最后一场比赛之前的空格字符正在匹配,这是不应该的。这是我正在使用的正则表达式:

(([0-9]* ??\(*([a-z]+[₀-₉]*)+\)*[₀-₉]*))

如果您查看此 regex101 链接,可能更容易看出我的问题是什么: https://regex101.com/r/hK7jY6/1

【问题讨论】:

最后没有看到空格匹配。 喜欢(((?:[0-9]+ )?\(*([a-z]+[₀-₉]*)+\)*[₀-₉]*))? @WiktorStribiżew 是的,这行得通。谢谢!随意张贴作为答案,我会接受它。 语言是什么? javascript @WiktorStribiżew 是的,它是 JavaScript。 【参考方案1】:

更新

如果您的字符串只是有效的化学公式,为什么还要使用下标/数字/字母呢?有非空白符号。由于必须有一个必填字母或(,因此在字符类[a-z(] 中使用它们,然后附加\S*(零个或多个非空格):

/(?:\d+ )?[a-z(]\S*/gi

请参阅regex demo。 (?:...)? 构造是一个可选的非捕获组(即仅用于分组但不捕获的组(=将子匹配存储在内存缓冲区中)。

带有根本原因解释的原始答案

您将开头的数字和空格模式作为可选子模式,相反,您需要强制匹配它们,但放入可选组中:

(?:[0-9]+ )?\(*([a-z]+[₀-₉]*)+\)*[₀-₉]*

见regex demo

您的[0-9]* ?? 变成了(?:[0-9]+ )?。请注意,在这里您不必使用 ? 量词的惰性版本,它的工作方式与贪婪的量词相同。我还删除了 2 个不必要的外部分组 (...)

由于(?:[0-9]+ )? 组是可选的,因此只有在其前面有数字时才会匹配空格。如果没有数字,则下一个可以匹配的字符是零个或多个(。然后,应该存在一个[a-z] 字母(如果没有(,则该字母将是匹配中的第一个字符)。

让我分解一下:

(?:[0-9]+ )? - 可选的一位或多位数字后跟一个空格 \(* - 零个或多个 ((也许你的意思是 ?([a-z]+[₀-₉]*)+ - 零个或多个一个或多个字母后跟零个或多个 sbscript 数字的序列 \)* - 零个或多个 )(也许你的意思是 ?[₀-₉]* - 零个或多个下标数字

如果您还想确保不匹配 (CaH),您还应该像这样拆分 \(*...\)*

(?:[0-9]+ )?(?:(?:[a-z]+[₀-₉]*)+|\((?:[a-z]+[₀-₉]*)+\))[₀-₉]*

见another demo

【讨论】:

所以因为整个组是可选的,所以在H2的情况下第一个空格不匹配对吧? 我添加了更多细节,我正在笔记本电脑上打字。我认为你仍然可以使这个表达式更好,但没有确切的要求,这就是我现在所能建议的。请注意,在字母之前还有一个可选的(。不确定这是预期的。另外,* 应用于\(,也许你只想要? 希望现在一切顺利。如果您需要正则表达式与 ECMAScript 5 (JS) 兼容,这就是我所能建议的。 太棒了!如果我还想匹配嵌套括号怎么办,就像在这个例子中一样? regex101.com/r/xY7rG8/33 ((Na₃Cl₂)₂HCl₄)₂₄ 将匹配。抱歉,我在写问题时忘记了这一点。 我对这种情况没有答案。您需要为此构建一个解析器。我会在几个小时内想到一个。【参考方案2】:

虽然 Wiktor 的回答内容丰富,但我想我可能已经找到了一种更简单的方法。

([0-9]+ )*[a-z\(₀-₉\)]+

据我所知,这将匹配方程式的所有部分。

Demo

更新

请参阅 Wiktors 更新答案,它比这更好。

【讨论】:

你没有说你有预先验证的字符串,你的模式暗示了这一点。如果您不需要任何预验证,我已经发布了另一个您可以使用的正则表达式。在您的正则表达式中,无需在字符类中转义 () 我明白了。那时我可能应该把它作为评论。再次感谢您的帮助。 @TobLoef 甚至like this: \b[\w₀-₉ )(]+(?!\S)

以上是关于为啥这个正则表达式在最后一场比赛中有空格?的主要内容,如果未能解决你的问题,请参考以下文章

允许单词之间有空格的正则表达式

正则表达式如何换行且有空格提取

正则表达式匹配一个精确的单词,它的前面或后面只能有空格等

仅在末尾有空格的字符串的正则表达式模式

正则表达式匹配特定长度的字符串,中间有空格(任何地方)

正则表达式:匹配模式后跟一个空格但不匹配2个或更多空格或EOF