在使用Perl处理大型文本化学数据库的过程中,我遇到了使用正则表达式匹配化学公式的问题。我以前看过these 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

(因此CCmCn将通过,但CgCx不会通过。)

与前面的问题一样,我也需要匹配数字,完整的括号和完整的方括号,以便例如C2H6O(CH3)2CFCOO(CH2)2Si(CH3)2Cl匹配。

那么,如何将先前的解决方案与大正则表达式结合使用,以匹配有效的化学元素以严格匹配化学式?

(如果添加起来不是很麻烦,那么对如何人为解析正则表达式的逐一介绍将是非常可取的,尽管并非绝对必要。)

最佳答案

简短的

我决定为什么不创建一个大型正则表达式来执行您想要的操作(但仍要保持干净的正则表达式)。此正则表达式将与循环结合使用,以遍历括号或括号组的匹配项。

假设条件

我假设以下内容是因为OP尚未提供正面和负面比赛的完整列表:

  • 不能嵌套括号
  • 嵌套的方括号是不可能的
  • 包围单个括号组的方括号组是多余的,因此
  • 不正确
  • 方括号组必须至少包含2个组,其中1个此类必须是括号组

  • 如果这些假设中的任何一个都不正确,请告诉我,以便我可以相应地修复正则表达式

    回答

    View this regex in use here

    代码
    (?(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中列出的每个元素之间的简单代码或|。确保每个元素的符号均按第一个字符的字母顺序排列,然后按符号字符长度的字母顺序排列(以免捕获例如Carbon 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和另一个组(ElementParenthesesGroupElementGroup)
  • 有效示例
  • [CH3(NO4)]-至少包含一个ElementParenthesesGroup和另一个ElementParenthesesGroupElementGroup
  • [(NO4)CH]2-包含至少一个ElementParenthesesGroup和另一个ElementParenthesesGroupElementGroup,后跟Num
  • [(NO4)(CH3)]-至少包含一个ElementParenthesesGroup和另一个ElementParenthesesGroupElementGroup
  • 无效的示例
  • [(NO4)]-不包含第二组,方括号[ ]是多余的
  • [NO4]-不包含ElementParenthesesGroup

  • 附加信息

    我知道这是一个很长的答案,但是OP提出了一个非常具体的问题,并希望确保满足特定的条件。

    确保设置了以下标志:
  • g-确保全局匹配
  • x-确保忽略空格
  • 如果数据跨多行(由换行符分隔),则将m用于多行

  • 注意:Regex只会捕获它找到的最后一组X类型的文件(并覆盖先前捕获的上述X类型的组。这是regex的默认行为,目前无法覆盖此行为。这可能会使您不满意您可以在链接的正则表达式中的最后一个示例以及(CH3)2CFCOO(CH2)2Si(CH3)2Cl的示例中看到此结果,因为每种组类型都有多个。

    10-08 00:42