匹配化学式的严格正则表达式
A strict regular expression for matching chemical formulae
在用Perl处理大型文本化学数据库的过程中,我曾遇到过使用正则表达式匹配化学式的问题。我看过 two 之前的主题,但那里的建议答案对我的要求来说太松散了。
具体来说,我的(公认的有限)研究使我 this posting 给出了当前接受的化学符号的正则表达式,我将在此处复制以供参考
[BCFHIKNOPSUVWY]|[ISZ][nr]|[ACELP][ru]|A[cglmst]|B[aehikr]|C[adeflos]|D[bsy]|Es|F[elmr]|G[ade]|H[efgos]|Kr|L[aiv]|M[cdgnot]|N[abdehiop]|O[gs]|P[abdmot]|R[abe-hnu]|S[bcegim]|T[abcehilms]|Xe|Yb
(因此 C
、Cm
和 Cn
将通过,但 Cg
或 Cx
不会通过。)
与前面的问题一样,我还需要匹配数字、完整的括号组和完整的方括号组,例如C2H6O
和 (CH3)2CFCOO(CH2)2Si(CH3)2Cl
匹配。
那么如何将前面的解决方案与匹配有效化学元素的大正则表达式结合起来以严格匹配化学式?
(如果添加起来不是太麻烦,将不胜感激如何人工解析正则表达式的详细说明,尽管并非绝对必要。)
最好不要手动 assemble 这么大的正则表达式。相反,让我们假设我们有一个原子数组 @atoms
。然后我们可以创建一个匹配任何这些原子的正则表达式,如:
my ($atoms_regex) = map qr/$_/, join '|', map quotemeta, sort @atoms;
(对所有项目进行排序,使较短的原子名称排在第一位,然后使用 quotemeta
转义所有项目,使用 |
将它们连接起来以备选,然后编译正则表达式。)
您可以将任何使用过的缩写添加到 @atoms
数组。
接下来,我们可以编写一个允许分组和编号的正则表达式。我们的正则表达式将匹配任意数量的项目,其中一个项目可以是一个原子或一个组,并且可以后跟一个数字:
my $chemical_formula_regex = qr/
(?&item)++
(?(DEFINE)
(?<item> (?: \((?&item)++\) | \[(?&item)++\] | $atoms_regex ) [0-9]* )
)
/x;
在 (?(DEFINE) ...)
组中,我们可以使用 (?<name> ...)
定义命名子模式。子模式就像正则表达式的子例程。我们可以用 (?&name)
调用这些子模式。这使我们能够在没有不必要重复的情况下构建正则表达式。
/x
标志允许我们使用空格、换行符和注释以更易读的方式布置正则表达式。正则表达式不必是一团乱麻!
用 ++
量词代替 +
不是绝对必要的,但可以防止不必要的回溯。当匹配失败时,这可能会更快一些。
简介
我决定为什么不创建一个庞大的正则表达式来做你想做的事(但仍然保持一个干净的正则表达式)。此正则表达式将与循环结合使用以遍历括号或圆括号组的匹配项。
假设
我假设如下,因为 OP 没有给出正面和负面匹配的完整列表:
- 嵌套括号是不可能的
- 不能嵌套方括号
- 包围单个括号组的方括号组是多余的,因此是不正确的
- 方括号组必须至少包含 2 个组,其中 1 个这样的组必须是括号组
如果这些假设中的任何一个不正确,请告诉我,以便我可以相应地修正正则表达式
回答
代码
(?(DEFINE)
(?# Periodic elements )
(?<Hydrogen>H)
(?<Helium>He)
(?<Lithium>Li)
(?<Beryllium>Be)
(?<Boron>B)
(?<Carbon>C)
(?<Nitrogen>N)
(?<Oxygen>O)
(?<Fluorine>F)
(?<Neon>Ne)
(?<Sodium>Na)
(?<Magnesium>Mg)
(?<Aluminum>Al)
(?<Silicon>Si)
(?<Phosphorus>P)
(?<Sulfur>S)
(?<Chlorine>Cl)
(?<Argon>Ar)
(?<Potassium>K)
(?<Calcium>Ca)
(?<Scandium>Sc)
(?<Titanium>Ti)
(?<Vanadium>V)
(?<Chromium>Cr)
(?<Manganese>Mn)
(?<Iron>Fe)
(?<Cobalt>Co)
(?<Nickel>Ni)
(?<Copper>Cu)
(?<Zinc>Zn)
(?<Gallium>Ga)
(?<Germanium>Ge)
(?<Arsenic>As)
(?<Selenium>Se)
(?<Bromine>Br)
(?<Krypton>Kr)
(?<Rubidium>Rb)
(?<Strontium>Sr)
(?<Yttrium>Y)
(?<Zirconium>Zr)
(?<Niobium>Nb)
(?<Molybdenum>Mo)
(?<Technetium>Tc)
(?<Ruthenium>Ru)
(?<Rhodium>Rh)
(?<Palladium>Pd)
(?<Silver>Ag)
(?<Cadmium>Cd)
(?<Indium>In)
(?<Tin>Sn)
(?<Antimony>Sb)
(?<Tellurium>Te)
(?<Iodine>I)
(?<Xenon>Xe)
(?<Cesium>Cs)
(?<Barium>Ba)
(?<Lanthanum>La)
(?<Cerium>Ce)
(?<Praseodymium>Pr)
(?<Neodymium>Nd)
(?<Promethium>Pm)
(?<Samarium>Sm)
(?<Europium>Eu)
(?<Gadolinium>Gd)
(?<Terbium>Tb)
(?<Dysprosium>Dy)
(?<Holmium>Ho)
(?<Erbium>Er)
(?<Thulium>Tm)
(?<Ytterbium>Yb)
(?<Lutetium>Lu)
(?<Hafnium>Hf)
(?<Tantalum>Ta)
(?<Tungsten>W)
(?<Rhenium>Re)
(?<Osmium>Os)
(?<Iridium>Ir)
(?<Platinum>Pt)
(?<Gold>Au)
(?<Mercury>Hg)
(?<Thallium>Tl)
(?<Lead>Pb)
(?<Bismuth>Bi)
(?<Polonium>Po)
(?<Astatine>At)
(?<Radon>Rn)
(?<Francium>Fr)
(?<Radium>Ra)
(?<Actinium>Ac)
(?<Thorium>Th)
(?<Protactinium>Pa)
(?<Uranium>U)
(?<Neptunium>Np)
(?<Plutonium>Pu)
(?<Americium>Am)
(?<Curium>Cm)
(?<Berkelium>Bk)
(?<Californium>Cf)
(?<Einsteinium>Es)
(?<Fermium>Fm)
(?<Mendelevium>Md)
(?<Nobelium>No)
(?<Lawrencium>Lr)
(?<Rutherfordium>Rf)
(?<Dubnium>Db)
(?<Seaborgium>Sg)
(?<Bohrium>Bh)
(?<Hassium>Hs)
(?<Meitnerium>Mt)
(?<Darmstadtium>Ds)
(?<Roentgenium>Rg)
(?<Copernicium>Cn)
(?<Nihonium>Nh)
(?<Flerovium>Fl)
(?<Moscovium>Mc)
(?<Livermorium>Lv)
(?<Tennessine>Ts)
(?<Oganesson>Og)
(?# Regex )
(?<Element>(?&Actinium)|(?&Silver)|(?&Aluminum)|(?&Americium)|(?&Argon)|(?&Arsenic)|(?&Astatine)|(?&Gold)|(?&Barium)|(?&Beryllium)|(?&Bohrium)|(?&Bismuth)|(?&Berkelium)|(?&Bromine)|(?&Boron)|(?&Calcium)|(?&Cadmium)|(?&Cerium)|(?&Californium)|(?&Chlorine)|(?&Curium)|(?&Copernicium)|(?&Cobalt)|(?&Chromium)|(?&Cesium)|(?&Copper)|(?&Carbon)|(?&Dubnium)|(?&Darmstadtium)|(?&Dysprosium)|(?&Erbium)|(?&Einsteinium)|(?&Europium)|(?&Iron)|(?&Flerovium)|(?&Fermium)|(?&Francium)|(?&Fluorine)|(?&Gallium)|(?&Gadolinium)|(?&Germanium)|(?&Helium)|(?&Hafnium)|(?&Mercury)|(?&Holmium)|(?&Hassium)|(?&Hydrogen)|(?&Indium)|(?&Iridium)|(?&Iodine)|(?&Krypton)|(?&Potassium)|(?&Lanthanum)|(?&Lithium)|(?&Lawrencium)|(?&Lutetium)|(?&Livermorium)|(?&Moscovium)|(?&Mendelevium)|(?&Magnesium)|(?&Manganese)|(?&Molybdenum)|(?&Meitnerium)|(?&Sodium)|(?&Niobium)|(?&Neodymium)|(?&Neon)|(?&Nihonium)|(?&Nickel)|(?&Nobelium)|(?&Neptunium)|(?&Nitrogen)|(?&Oganesson)|(?&Osmium)|(?&Oxygen)|(?&Protactinium)|(?&Lead)|(?&Palladium)|(?&Promethium)|(?&Polonium)|(?&Praseodymium)|(?&Platinum)|(?&Plutonium)|(?&Phosphorus)|(?&Radium)|(?&Rubidium)|(?&Rhenium)|(?&Rutherfordium)|(?&Roentgenium)|(?&Rhodium)|(?&Radon)|(?&Ruthenium)|(?&Antimony)|(?&Scandium)|(?&Selenium)|(?&Seaborgium)|(?&Silicon)|(?&Samarium)|(?&Tin)|(?&Strontium)|(?&Sulfur)|(?&Tantalum)|(?&Terbium)|(?&Technetium)|(?&Tellurium)|(?&Thorium)|(?&Titanium)|(?&Thallium)|(?&Thulium)|(?&Tennessine)|(?&Uranium)|(?&Vanadium)|(?&Tungsten)|(?&Xenon)|(?&Ytterbium)|(?&Yttrium)|(?&Zirconium)|(?&Zinc))
(?<Num>(?:[1-9]\d*)?)
(?<ElementGroup>(?:(?&Element)(?&Num))+)
(?<ElementParenthesesGroup>\((?&ElementGroup)+\)(?&Num))
(?<ElementSquareBracketGroup>\[(?:(?:(?&ElementParenthesesGroup)(?:(?&ElementGroup)|(?&ElementParenthesesGroup))+)|(?:(?:(?&ElementGroup)|(?&ElementParenthesesGroup))+(?&ElementParenthesesGroup)))\](?&Num))
)
^((?<Brackets>(?&ElementSquareBracketGroup))|(?<Parentheses>(?&ElementParenthesesGroup))|(?<Group>(?&ElementGroup)))+$
说明
(?(DEFINE))
部分的第一部分列出了每个周期元素(按原子序数排序以便于查找)。
Element
组充当 1 中列出的每个元素之间的简单或 |
。确保每个元素的符号按第一个字符的字母顺序排序,然后按符号字符长度排序(以免捕获,例如,碳 C
而不是钙 Ca
)
ElementGroup
以以下格式指定一组化学品:一个或多个 Element
后跟零个或多个数字,不包括零(由组 Num
指定)
- 有效示例
C
- Element
CH
- Element
接着是另一个 Element
CH3
-Element
接着是另一个 Element
和一个 Num
O2
- Element
后跟 Num
- 无效示例
N0
- 0
不能明确使用
N01
- Num
组指定号码必须以1-9
开头或没有号码
A
- 元素不存在
c
- 元素不存在 - 区分大小写的正则表达式
ElementParenthesesGroup
在括号 (
)
之间指定一个或多个 ElementGroup
的分组,但至少包含一个 ElementGroup
- 有效示例
(CH)
- ElementGroup
括号
(CH3)
- ElementGroup
括号
(CH3NO4)
- 多个 ElementGroup
被圆括号 包围
(CH3N04)2
- 多个 ElementGroup
被括号包围,后跟 Num
- 无效示例
(CH[NO4])
- 只有 ElementGroup
在 ElementParenthesesGroup
中有效
ElementSquareBracketGroup
指定一组 ElementParenthesesGroup
或 ElementGroup
在方括号 [
]
之间但至少包含一个 ElementParenthesesGroup
和一个其他组(ElementParenthesesGroup
或 ElementGroup
)
- 有效示例
[CH3(NO4)]
- 至少包含一个 ElementParenthesesGroup
和另一个 ElementParenthesesGroup
或 ElementGroup
[(NO4)CH]2
- 包含至少一个 ElementParenthesesGroup
和另一个 ElementParenthesesGroup
或 ElementGroup
后跟 Num
[(NO4)(CH3)]
- 至少包含一个 ElementParenthesesGroup
和另一个 ElementParenthesesGroup
或 ElementGroup
- 无效示例
[(NO4)]
- 不包含第二组,括号 [
]
是多余的
[NO4]
- 不包含 ElementParenthesesGroup
附加信息
我知道这是一个很长的答案,但 OP 提出了一个非常具体的问题,并希望确保满足特定标准。
确保设置了以下标志:
g
- 确保全局匹配
x
- 确保忽略空格
- 如果数据跨越多行(由换行符分隔),则对多行使用
m
注意:正则表达式只会捕获它找到的最后一组类型 X
(并覆盖先前捕获的所述类型 X
的组)。这是正则表达式的默认行为,并且有目前无法覆盖此行为。这可能会给您带来不良结果。您可以在链接的正则表达式中的最后一个示例以及 (CH3)2CFCOO(CH2)2Si(CH3)2Cl
示例中看到这一点,因为每个组类型都有多个。
因为这个 post 是“regex chemistry symbols”的最佳结果,我也想提交一个解决方案。这是一个 python 脚本,它使用正则表达式来匹配 A#B# 类型的化学公式,其中 A 和 B 是化学符号,# 是数字。执行的脚本匹配,然后用 \ce{} 包围匹配,以便在 LaTeX 中使用。如果捕获在用户定义的列表中,它还包括排除匹配项的能力,这意味着不会匹配诸如“I”和“In”之类的词。 Gist Link.
#!/usr/bin/env python3
# Find chemical symbols and surround them with \ce{ Symbol }
# Problem words: I, HOW, In, degrees K. Add words to exlist to ignore them.
import re, sys
if len(sys.argv) < 2 :
print('Usage:> {} <filename>'.format(sys.argv[0]))
sys.exit(1)
ptable =" H He "
ptable+=" Li Be B C N O F Ne "
ptable+=" Na Mg Al Si P S Cl Ar "
ptable+=" K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr "
ptable+=" Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe "
ptable+=" Cs Ba La Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn "
ptable+=" Fr Ra Ac Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og "
ptable+=" Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu "
ptable+=" Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr "
exlist = ['C','I','In','K','HOW'] # exclude these words from being replaced
orsyms = '|'.join(ptable.split())
resyms = re.compile(r'\b'+'((?:(?:{})\d*)+)'.format(orsyms)+r'\b')
latexfile=sys.argv[1]
with open(latexfile,'r') as fd:
for line in fd:
for m in list(set(resyms.findall(line))):
if m not in exlist :
line = re.sub(r'\b'+m+r'\b', r'\ce{'+m+r'}', line)
print(line,end='')
在用Perl处理大型文本化学数据库的过程中,我曾遇到过使用正则表达式匹配化学式的问题。我看过
具体来说,我的(公认的有限)研究使我 this posting 给出了当前接受的化学符号的正则表达式,我将在此处复制以供参考
[BCFHIKNOPSUVWY]|[ISZ][nr]|[ACELP][ru]|A[cglmst]|B[aehikr]|C[adeflos]|D[bsy]|Es|F[elmr]|G[ade]|H[efgos]|Kr|L[aiv]|M[cdgnot]|N[abdehiop]|O[gs]|P[abdmot]|R[abe-hnu]|S[bcegim]|T[abcehilms]|Xe|Yb
(因此 C
、Cm
和 Cn
将通过,但 Cg
或 Cx
不会通过。)
与前面的问题一样,我还需要匹配数字、完整的括号组和完整的方括号组,例如C2H6O
和 (CH3)2CFCOO(CH2)2Si(CH3)2Cl
匹配。
那么如何将前面的解决方案与匹配有效化学元素的大正则表达式结合起来以严格匹配化学式?
(如果添加起来不是太麻烦,将不胜感激如何人工解析正则表达式的详细说明,尽管并非绝对必要。)
最好不要手动 assemble 这么大的正则表达式。相反,让我们假设我们有一个原子数组 @atoms
。然后我们可以创建一个匹配任何这些原子的正则表达式,如:
my ($atoms_regex) = map qr/$_/, join '|', map quotemeta, sort @atoms;
(对所有项目进行排序,使较短的原子名称排在第一位,然后使用 quotemeta
转义所有项目,使用 |
将它们连接起来以备选,然后编译正则表达式。)
您可以将任何使用过的缩写添加到 @atoms
数组。
接下来,我们可以编写一个允许分组和编号的正则表达式。我们的正则表达式将匹配任意数量的项目,其中一个项目可以是一个原子或一个组,并且可以后跟一个数字:
my $chemical_formula_regex = qr/
(?&item)++
(?(DEFINE)
(?<item> (?: \((?&item)++\) | \[(?&item)++\] | $atoms_regex ) [0-9]* )
)
/x;
在
(?(DEFINE) ...)
组中,我们可以使用(?<name> ...)
定义命名子模式。子模式就像正则表达式的子例程。我们可以用(?&name)
调用这些子模式。这使我们能够在没有不必要重复的情况下构建正则表达式。/x
标志允许我们使用空格、换行符和注释以更易读的方式布置正则表达式。正则表达式不必是一团乱麻!用
++
量词代替+
不是绝对必要的,但可以防止不必要的回溯。当匹配失败时,这可能会更快一些。
简介
我决定为什么不创建一个庞大的正则表达式来做你想做的事(但仍然保持一个干净的正则表达式)。此正则表达式将与循环结合使用以遍历括号或圆括号组的匹配项。
假设
我假设如下,因为 OP 没有给出正面和负面匹配的完整列表:
- 嵌套括号是不可能的
- 不能嵌套方括号
- 包围单个括号组的方括号组是多余的,因此是不正确的
- 方括号组必须至少包含 2 个组,其中 1 个这样的组必须是括号组
如果这些假设中的任何一个不正确,请告诉我,以便我可以相应地修正正则表达式
回答
代码
(?(DEFINE)
(?# Periodic elements )
(?<Hydrogen>H)
(?<Helium>He)
(?<Lithium>Li)
(?<Beryllium>Be)
(?<Boron>B)
(?<Carbon>C)
(?<Nitrogen>N)
(?<Oxygen>O)
(?<Fluorine>F)
(?<Neon>Ne)
(?<Sodium>Na)
(?<Magnesium>Mg)
(?<Aluminum>Al)
(?<Silicon>Si)
(?<Phosphorus>P)
(?<Sulfur>S)
(?<Chlorine>Cl)
(?<Argon>Ar)
(?<Potassium>K)
(?<Calcium>Ca)
(?<Scandium>Sc)
(?<Titanium>Ti)
(?<Vanadium>V)
(?<Chromium>Cr)
(?<Manganese>Mn)
(?<Iron>Fe)
(?<Cobalt>Co)
(?<Nickel>Ni)
(?<Copper>Cu)
(?<Zinc>Zn)
(?<Gallium>Ga)
(?<Germanium>Ge)
(?<Arsenic>As)
(?<Selenium>Se)
(?<Bromine>Br)
(?<Krypton>Kr)
(?<Rubidium>Rb)
(?<Strontium>Sr)
(?<Yttrium>Y)
(?<Zirconium>Zr)
(?<Niobium>Nb)
(?<Molybdenum>Mo)
(?<Technetium>Tc)
(?<Ruthenium>Ru)
(?<Rhodium>Rh)
(?<Palladium>Pd)
(?<Silver>Ag)
(?<Cadmium>Cd)
(?<Indium>In)
(?<Tin>Sn)
(?<Antimony>Sb)
(?<Tellurium>Te)
(?<Iodine>I)
(?<Xenon>Xe)
(?<Cesium>Cs)
(?<Barium>Ba)
(?<Lanthanum>La)
(?<Cerium>Ce)
(?<Praseodymium>Pr)
(?<Neodymium>Nd)
(?<Promethium>Pm)
(?<Samarium>Sm)
(?<Europium>Eu)
(?<Gadolinium>Gd)
(?<Terbium>Tb)
(?<Dysprosium>Dy)
(?<Holmium>Ho)
(?<Erbium>Er)
(?<Thulium>Tm)
(?<Ytterbium>Yb)
(?<Lutetium>Lu)
(?<Hafnium>Hf)
(?<Tantalum>Ta)
(?<Tungsten>W)
(?<Rhenium>Re)
(?<Osmium>Os)
(?<Iridium>Ir)
(?<Platinum>Pt)
(?<Gold>Au)
(?<Mercury>Hg)
(?<Thallium>Tl)
(?<Lead>Pb)
(?<Bismuth>Bi)
(?<Polonium>Po)
(?<Astatine>At)
(?<Radon>Rn)
(?<Francium>Fr)
(?<Radium>Ra)
(?<Actinium>Ac)
(?<Thorium>Th)
(?<Protactinium>Pa)
(?<Uranium>U)
(?<Neptunium>Np)
(?<Plutonium>Pu)
(?<Americium>Am)
(?<Curium>Cm)
(?<Berkelium>Bk)
(?<Californium>Cf)
(?<Einsteinium>Es)
(?<Fermium>Fm)
(?<Mendelevium>Md)
(?<Nobelium>No)
(?<Lawrencium>Lr)
(?<Rutherfordium>Rf)
(?<Dubnium>Db)
(?<Seaborgium>Sg)
(?<Bohrium>Bh)
(?<Hassium>Hs)
(?<Meitnerium>Mt)
(?<Darmstadtium>Ds)
(?<Roentgenium>Rg)
(?<Copernicium>Cn)
(?<Nihonium>Nh)
(?<Flerovium>Fl)
(?<Moscovium>Mc)
(?<Livermorium>Lv)
(?<Tennessine>Ts)
(?<Oganesson>Og)
(?# Regex )
(?<Element>(?&Actinium)|(?&Silver)|(?&Aluminum)|(?&Americium)|(?&Argon)|(?&Arsenic)|(?&Astatine)|(?&Gold)|(?&Barium)|(?&Beryllium)|(?&Bohrium)|(?&Bismuth)|(?&Berkelium)|(?&Bromine)|(?&Boron)|(?&Calcium)|(?&Cadmium)|(?&Cerium)|(?&Californium)|(?&Chlorine)|(?&Curium)|(?&Copernicium)|(?&Cobalt)|(?&Chromium)|(?&Cesium)|(?&Copper)|(?&Carbon)|(?&Dubnium)|(?&Darmstadtium)|(?&Dysprosium)|(?&Erbium)|(?&Einsteinium)|(?&Europium)|(?&Iron)|(?&Flerovium)|(?&Fermium)|(?&Francium)|(?&Fluorine)|(?&Gallium)|(?&Gadolinium)|(?&Germanium)|(?&Helium)|(?&Hafnium)|(?&Mercury)|(?&Holmium)|(?&Hassium)|(?&Hydrogen)|(?&Indium)|(?&Iridium)|(?&Iodine)|(?&Krypton)|(?&Potassium)|(?&Lanthanum)|(?&Lithium)|(?&Lawrencium)|(?&Lutetium)|(?&Livermorium)|(?&Moscovium)|(?&Mendelevium)|(?&Magnesium)|(?&Manganese)|(?&Molybdenum)|(?&Meitnerium)|(?&Sodium)|(?&Niobium)|(?&Neodymium)|(?&Neon)|(?&Nihonium)|(?&Nickel)|(?&Nobelium)|(?&Neptunium)|(?&Nitrogen)|(?&Oganesson)|(?&Osmium)|(?&Oxygen)|(?&Protactinium)|(?&Lead)|(?&Palladium)|(?&Promethium)|(?&Polonium)|(?&Praseodymium)|(?&Platinum)|(?&Plutonium)|(?&Phosphorus)|(?&Radium)|(?&Rubidium)|(?&Rhenium)|(?&Rutherfordium)|(?&Roentgenium)|(?&Rhodium)|(?&Radon)|(?&Ruthenium)|(?&Antimony)|(?&Scandium)|(?&Selenium)|(?&Seaborgium)|(?&Silicon)|(?&Samarium)|(?&Tin)|(?&Strontium)|(?&Sulfur)|(?&Tantalum)|(?&Terbium)|(?&Technetium)|(?&Tellurium)|(?&Thorium)|(?&Titanium)|(?&Thallium)|(?&Thulium)|(?&Tennessine)|(?&Uranium)|(?&Vanadium)|(?&Tungsten)|(?&Xenon)|(?&Ytterbium)|(?&Yttrium)|(?&Zirconium)|(?&Zinc))
(?<Num>(?:[1-9]\d*)?)
(?<ElementGroup>(?:(?&Element)(?&Num))+)
(?<ElementParenthesesGroup>\((?&ElementGroup)+\)(?&Num))
(?<ElementSquareBracketGroup>\[(?:(?:(?&ElementParenthesesGroup)(?:(?&ElementGroup)|(?&ElementParenthesesGroup))+)|(?:(?:(?&ElementGroup)|(?&ElementParenthesesGroup))+(?&ElementParenthesesGroup)))\](?&Num))
)
^((?<Brackets>(?&ElementSquareBracketGroup))|(?<Parentheses>(?&ElementParenthesesGroup))|(?<Group>(?&ElementGroup)))+$
说明
(?(DEFINE))
部分的第一部分列出了每个周期元素(按原子序数排序以便于查找)。Element
组充当 1 中列出的每个元素之间的简单或|
。确保每个元素的符号按第一个字符的字母顺序排序,然后按符号字符长度排序(以免捕获,例如,碳C
而不是钙Ca
)ElementGroup
以以下格式指定一组化学品:一个或多个Element
后跟零个或多个数字,不包括零(由组Num
指定)- 有效示例
C
-Element
CH
-Element
接着是另一个Element
CH3
-Element
接着是另一个Element
和一个Num
O2
-Element
后跟Num
- 无效示例
N0
-0
不能明确使用N01
-Num
组指定号码必须以1-9
开头或没有号码A
- 元素不存在c
- 元素不存在 - 区分大小写的正则表达式
- 有效示例
ElementParenthesesGroup
在括号(
)
之间指定一个或多个ElementGroup
的分组,但至少包含一个ElementGroup
- 有效示例
(CH)
-ElementGroup
括号(CH3)
-ElementGroup
括号(CH3NO4)
- 多个ElementGroup
被圆括号 包围
(CH3N04)2
- 多个ElementGroup
被括号包围,后跟Num
- 无效示例
(CH[NO4])
- 只有ElementGroup
在ElementParenthesesGroup
中有效
- 有效示例
ElementSquareBracketGroup
指定一组ElementParenthesesGroup
或ElementGroup
在方括号[
]
之间但至少包含一个ElementParenthesesGroup
和一个其他组(ElementParenthesesGroup
或ElementGroup
)- 有效示例
[CH3(NO4)]
- 至少包含一个ElementParenthesesGroup
和另一个ElementParenthesesGroup
或ElementGroup
[(NO4)CH]2
- 包含至少一个ElementParenthesesGroup
和另一个ElementParenthesesGroup
或ElementGroup
后跟Num
[(NO4)(CH3)]
- 至少包含一个ElementParenthesesGroup
和另一个ElementParenthesesGroup
或ElementGroup
- 无效示例
[(NO4)]
- 不包含第二组,括号[
]
是多余的[NO4]
- 不包含ElementParenthesesGroup
- 有效示例
附加信息
我知道这是一个很长的答案,但 OP 提出了一个非常具体的问题,并希望确保满足特定标准。
确保设置了以下标志:
g
- 确保全局匹配x
- 确保忽略空格- 如果数据跨越多行(由换行符分隔),则对多行使用
m
注意:正则表达式只会捕获它找到的最后一组类型 X
(并覆盖先前捕获的所述类型 X
的组)。这是正则表达式的默认行为,并且有目前无法覆盖此行为。这可能会给您带来不良结果。您可以在链接的正则表达式中的最后一个示例以及 (CH3)2CFCOO(CH2)2Si(CH3)2Cl
示例中看到这一点,因为每个组类型都有多个。
因为这个 post 是“regex chemistry symbols”的最佳结果,我也想提交一个解决方案。这是一个 python 脚本,它使用正则表达式来匹配 A#B# 类型的化学公式,其中 A 和 B 是化学符号,# 是数字。执行的脚本匹配,然后用 \ce{} 包围匹配,以便在 LaTeX 中使用。如果捕获在用户定义的列表中,它还包括排除匹配项的能力,这意味着不会匹配诸如“I”和“In”之类的词。 Gist Link.
#!/usr/bin/env python3
# Find chemical symbols and surround them with \ce{ Symbol }
# Problem words: I, HOW, In, degrees K. Add words to exlist to ignore them.
import re, sys
if len(sys.argv) < 2 :
print('Usage:> {} <filename>'.format(sys.argv[0]))
sys.exit(1)
ptable =" H He "
ptable+=" Li Be B C N O F Ne "
ptable+=" Na Mg Al Si P S Cl Ar "
ptable+=" K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr "
ptable+=" Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe "
ptable+=" Cs Ba La Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn "
ptable+=" Fr Ra Ac Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og "
ptable+=" Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu "
ptable+=" Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr "
exlist = ['C','I','In','K','HOW'] # exclude these words from being replaced
orsyms = '|'.join(ptable.split())
resyms = re.compile(r'\b'+'((?:(?:{})\d*)+)'.format(orsyms)+r'\b')
latexfile=sys.argv[1]
with open(latexfile,'r') as fd:
for line in fd:
for m in list(set(resyms.findall(line))):
if m not in exlist :
line = re.sub(r'\b'+m+r'\b', r'\ce{'+m+r'}', line)
print(line,end='')