【问题标题】: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。

标签: regex


【解决方案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)
猜你喜欢
  • 2021-03-29
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多