为啥这个正则表达式在最后一场比赛中有空格?
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 数字的序列
\)*
- 零个或多个 )
(也许你的意思是 ?
)
[₀-₉]*
- 零个或多个下标数字
如果您还想确保不匹配 (Ca
或 H)
,您还应该像这样拆分 \(*...\)*
:
(?:[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)
以上是关于为啥这个正则表达式在最后一场比赛中有空格?的主要内容,如果未能解决你的问题,请参考以下文章