6

我有一个表达式,我需要拆分并存储在一个数组中:

aaa="bbb{ccc}ddd" { aa="bb,cc" { a="b", c="d" } }, aaa="bbb{}" { aa="b}b" }, aaa="bbb,ccc"

一旦拆分并存储在数组中,它应该看起来像这样:

aaa="bbb{ccc}ddd" { aa="bb,cc" { a="b", c="d" } }
aaa="bbb{}" { aa="b}b" }
aaa="bbb,ccc"

我使用 Perl 5.8 版,有人可以解决这个问题吗?

4

6 回答 6

11

使用 perl 模块“Regexp::Common”。它有一个很好的平衡括号正则表达式,效果很好。

# ASN.1
use Regexp::Common;
$bp = $RE{balanced}{-parens=>'{}'};
@genes = $l =~ /($bp)/g;
于 2012-08-22T02:12:58.373 回答
9

perlre中有一个示例,使用 v5.10 中引入的递归正则表达式功能。尽管您仅限于 v5.8,但其他提出此问题的人应该得到正确的解决方案:)

$re = qr{ 
            (                                # paren group 1 (full function)
                foo
                (                            # paren group 2 (parens)
                    \(
                        (                    # paren group 3 (contents of parens)
                            (?:
                                (?> [^()]+ ) # Non-parens without backtracking
                                |
                                (?2)         # Recurse to start of paren group 2
                            )*
                        )
                    \)
                )
            )
    }x;
于 2013-10-01T17:19:54.623 回答
1

我或多或少同意 Scott Rippey 关于编写自己的解析器的观点。这是一个简单的:

my $in = 'aaa="bbb{ccc}ddd" { aa="bb,cc" { a="b", c="d" } }, ' .
         'aaa="bbb{}" { aa="b}b" }, ' .
         'aaa="bbb,ccc"'
;

my @out = ('');

my $nesting = 0;
while($in !~ m/\G$/cg)
{
  if($nesting == 0 && $in =~ m/\G,\s*/cg)
  {
    push @out, '';
    next;
  }
  if($in =~ m/\G(\{+)/cg)
    { $nesting += length $1; }
  elsif($in =~ m/\G(\}+)/cg)
  {
    $nesting -= length $1;
    die if $nesting < 0;
  }
  elsif($in =~ m/\G((?:[^{}"]|"[^"]*")+)/cg)
    { }
  else
    { die; }
  $out[-1] .= $1;
}

(在 Perl 5.10 中测试;抱歉,我手边没有 Perl 5.8,但据我所知没有任何相关的差异。)不用说,你会想die用特定于应用程序的东西替换 s。而且您可能必须调整上述内容以处理示例中未包含的情况。(例如,引用的字符串是否可以包含\"? 可以'用来代替"? 此代码不处理任何一种可能性。)

于 2011-11-02T01:45:43.747 回答
1

为了匹配平衡括号或大括号,并且如果您想考虑反斜杠(转义),建议的解决方案将不起作用。相反,你会写这样的东西(基于perlre中建议的解决方案):

$re = qr/
(                                                # paren group 1 (full function)
    foo
    (?<paren_group>                              # paren group 2 (parens)
        \(
            (                                    # paren group 3 (contents of parens)
                (?:
                    (?> (?:\\[()]|(?![()]).)+ )  # escaped parens or no parens
                    |
                    (?&paren_group)              # Recurse to named capture group
                )*
            )
        \)
    )
)
/x;
于 2021-02-22T07:51:12.110 回答
0

尝试这样的事情:

use strict;
use warnings;
use Data::Dumper;

my $exp=<<END;
aaa="bbb{ccc}ddd" { aa="bb,cc" { a="b", c="d" } }     , aaa="bbb{}" { aa="b}b" }, aaa="bbb,ccc"
END

chomp $exp;
my @arr = map { $_ =~ s/^\s*//; $_ =~ s/\s* $//; "$_}"} split('}\s*,',$exp);
print Dumper(\@arr);
于 2011-11-01T23:48:36.123 回答
-1

尽管递归正则表达式通常可用于捕获“平衡大括号” {},但它们对您不起作用,因为您还需要匹配“平衡引号” "
对于 Perl 正则表达式来说,这将是一项非常棘手的任务,我相当肯定这是不可能的。(相比之下,它可能可以通过Microsoft 的“平衡组”Regex 功能来完成)。

我建议创建自己的解析器。在处理每个字符时,您计算每个"and ,并且仅在它们“平衡”{}时才拆分。,

于 2011-11-02T01:11:58.383 回答