为什么这个正则表达式空间在最后一场比赛?

时间:2016-02-06 15:01:02

标签: regex

我有以下文字:

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

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

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

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

2 个答案:

答案 0 :(得分:5)

更新

如果您的字符串只是有效的化学公式,为什么还要使用下标/数字/字母呢?有非空白符号。由于必须有必填字母或(,请在字符类[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

答案 1 :(得分:2)

虽然Wiktor的回答非常有用,但我想我可能已经找到了一种更简单的方法。

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

就我所知,这将与等式的所有部分相匹配。

Demo

<强>更新

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