【问题标题】:perl regex to get comma not in parenthesis or nested parenthesisperl 正则表达式获取逗号不在括号或嵌套括号中
【发布时间】:2020-04-27 11:34:02
【问题描述】:

我有一个逗号分隔的字符串,我想匹配每个不在括号中的逗号(括号保证是平衡的)。

a   ,   (b)  ,   (d$_,c)    ,     ((,),d,(,))

a 和 (b)、(b) 和 (d$,c)、(d$,c) 和 ((,),d,(,)) 之间的逗号应该匹配但不在 (d$_,c) 或 ((,),d,(,)) 内。

注意:最终我想用这些逗号分割字符串。

它尝试了这个正则表达式: (?!<(?:\(|\[)[^)\]]+),(?![^(\[]+(?:\)|\])) 来自 here 但它仅适用于非嵌套括号。

【问题讨论】:

    标签: regex perl pcre


    【解决方案1】:

    你可以使用

    (\((?:[^()]++|(?1))*\))(*SKIP)(*F)|,
    

    regex demo

    详情

    • (\((?:[^()]++|(?1))*\)) - 捕获组 1:匹配平衡括号之间的子字符串:
      • \( - 一个 ( 字符
      • (?:[^()]++|(?1))* - 除了 () 或整个 Group 1 模式之外,零个或多个 1+ 字符出现(由于 regex subroutine (?1) 在这里是必要的,因为只有整个正则表达式模式的一部分是递归的)
      • \) - ) 字符。
    • (*SKIP)(*F) - 忽略找到的匹配项并从匹配项的末尾开始下一次搜索
    • | - 或
    • , - 匹配嵌套括号外的逗号。

    【讨论】:

    • 这正是我所需要的。完美!
    【解决方案2】:

    用于此的单个正则表达式过于复杂且难以维护或扩展。这是一个迭代解析器方法:

    use strict;
    use warnings;
    
    my $str = 'a   ,   (b)  ,   (d$_,c)    ,     ((,),d,(,))';
    
    my $nesting = 0;
    my $buffer = '';
    my @vals;
    while ($str =~ m/\G([,()]|[^,()]+)/g) {
      my $token = $1;
      if ($token eq ',' and !$nesting) {
        push @vals, $buffer;
        $buffer = '';
      } else {
        $buffer .= $token;
        if ($token eq '(') {
          $nesting++;
        } elsif ($token eq ')') {
          $nesting--;
        }
      }
    }
    push @vals, $buffer if length $buffer;
    
    print "$_\n" for @vals;
    

    您可以使用Parser::MGC 更抽象地构造这种解析器。

    【讨论】:

    • 另一个答案给出了解决方案。对于我的项目,我使用了一个解析器库来完成所有繁重的工作。我使用这个正则表达式只是为了漂亮的打印,因为解析器库没有公开这个 API,所以我知道需要替换哪些参数。维护它不是优先事项,因为我不会比这更深入。
    • 已更改为此答案。其他答案有分裂的问题。 Check here
    猜你喜欢
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    相关资源
    最近更新 更多