【问题标题】:RegEx for parsing chemical formulas用于解析化学式的正则表达式
【发布时间】:2014-05-12 06:14:26
【问题描述】:

我需要一种方法来将化学式分解为其组成部分。结果应该看起来像 这个:

   Ag3PO4 -> [Ag3, P, O4]
      H2O -> [H2, O]
   CH3OOH -> [C, H3, O, O, H]
Ca3(PO4)2 -> [Ca3, (PO4)2]

我不知道正则表达式的语法,但我知道我需要这样的东西

[可选括号][大写字母][0个或多个小写字母][0个或多个数字][可选括号][0个或多个数字]

成功了

NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:@"[A-Z][a-z]*\\d*|\\([^)]+\\)\\d*"
                              options:0
                              error:nil];
NSArray *tests = [[NSArray alloc ] initWithObjects:@"Ca3(PO4)2", @"HCl", @"CaCO3", @"ZnCl2", @"C7H6O2", @"BaSO4", nil];
for (NSString *testString in tests)
{
    NSLog(@"Testing: %@", testString);
    NSArray *myArray = [regex matchesInString:testString options:0 range:NSMakeRange(0, [testString length])] ;
    NSMutableArray *matches = [NSMutableArray arrayWithCapacity:[myArray count]];

    for (NSTextCheckingResult *match in myArray) {
        NSRange matchRange = [match rangeAtIndex:0];
        [matches addObject:[testString substringWithRange:matchRange]];
        NSLog(@"%@", [matches lastObject]);
    }
}

【问题讨论】:

  • 我不确定化学公式是否是常规语言。你也许可以尝试一下,但它可能并不完美。
  • @LegoStormtroopr 看看我上面的尝试,只要我能得到类似的东西,我就会很酷。

标签: objective-c regex


【解决方案1】:

(PO4)2 真的置身事外。

让我们从简单的不带括号的匹配项开始:

[A-Z][a-z]?\d*

使用上面的正则表达式我们可以成功解析Ag3PO4H2OCH3OOH

然后我们需要以某种方式为组添加表达式。组本身可以使用:

\(.*?\)\d+

所以我们添加or条件:

[A-Z][a-z]?\d*|\(.*?\)\d+

Demo

适用于特定情况。但可能您还有更多样本。

注意:嵌套括号会有问题。前任。 Co3(Fe(CN)6)2

如果您想处理这种情况,可以使用以下正则表达式:

[A-Z][a-z]?\d*|(?<!\([^)]*)\(.*\)\d+(?![^(]*\))

对于 Objective-C,您可以使用没有环视的表达式:

[A-Z][a-z]?\d*|\([^()]*(?:\(.*\))?[^()]*\)\d+

Demo

或带有重复的正则表达式(我不知道这样的公式,但如果有类似A(B(CD)3E(FG)4)5 的东西 - 一个内有多个括号块。

[A-Z][a-z]?\d*|\((?:[^()]*(?:\(.*\))?[^()]*)+\)\d+

Demo

【讨论】:

  • 感谢一群人,感谢所有其他海报的快速帮助。这真的有助于我理解正则表达式,它们都能完成工作!
  • 我不经常遇到双括号,但就目前而言,它们是一个问题,因为Co3(Fe(CN)6)2 产生[Co3, (Fe(CN)6]
  • @doctordoder 它错过了2,应该是(Fe(CN)6)2。我添加了正则表达式来处理这种情况。
  • 我在您上次编辑时遇到了一些问题。不过,我认为这只是一个 Objective-C 的东西。例如,每个 \ 都需要写为 \\ 因为它们是 NSString 对象。这是我尝试过的,但每次测试都没有匹配项:gist.github.com/MichaelSnowden/e5badcffeb7c4300d067
  • 题外话,但是你是如何生成正则表达式模式的那些时髦的可视化的?
【解决方案2】:

遇到括号组,你不会想解析里面的内容吧?

如果没有嵌套的括号组,您可以简单地使用

[A-Z][a-z]*\d*|\([^)]+\)\d*

\d[0-9] 的快捷方式,[^)] 的意思不是括号。

demo here

【讨论】:

    【解决方案3】:

    这应该只是工作:

    /(\(?)([A-Z])([a-z]*)([0-9]*)(\))?([0-9]*)/g
    

    在这里玩一下:http://refiddle.com/

    【讨论】:

    • 为什么所有的捕获组?
    • 我以为 OP 希望每个部分都单独匹配。
    【解决方案4】:

    这个模式应该取决于你的 RegEx 引擎
    ([A-Z][a-z]*\d*)|(\((?:[^()]+|(?R))*\)\d*)gm 选项
    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      • 2022-01-25
      • 2012-07-01
      • 1970-01-01
      • 2012-10-17
      相关资源
      最近更新 更多