3

我想要一个正则表达式来匹配分隔值和一些可以包含分隔符的受保护值。

例如:

"A,B,{C,D,E},F"

会给:

  • “一种”
  • “乙”
  • “{C,D,E}”
  • “F”

请注意,受保护的值可以嵌套,如下所示:

"A,B,{C,D,{E,F}},G"

会给:

  • “一种”
  • “乙”
  • “{C,D,{E,F}}”
  • “G”

我已经使用字符迭代对该功能进行了编码,如下所示:

sub Parse
{
  my @item;

  my $curly;
  my $string;
  foreach(split //)
  {
    $_ eq "{" and ++$curly;
    $_ eq "}" and --$curly;

    if(!$curly && /[,:]/)
    {
      push @item, $string;
      undef $string;
      next;
    }
    $string .= $_;
  }

  push @item, $string;
  return @item;
}

但是使用正则表达式肯定会更好。

4

6 回答 6

2

支持嵌套的正则表达式如下所示:

my @items;
push @items, $1 while
   /
      (?: ^ | \G , )
      (
         (?: [^,{}]+
         |   (
                \{
                   (?: [^{}]
                   |   (?2)
                   )*
                \}
             )
         |   # Empty
         )
      )
   /xg;

$ perl -E'$_ = shift; ... say for @items;' 'A,B,{C,D,{E,F}},G'
A
B
{C,D,{E,F}}
G

假定输入有效,因为它不能同时提取和验证。(好吧,不是没有让事情变得非常混乱。)

于 2012-07-27T18:35:19.523 回答
1
$a = "A,B,{C,D,E},F";
while ($a =~ s/(\{[\{\}\w,]+\}|\w)//) {
    push (@res, $1);
}
print "\@res: @res\n"

结果:

@res: A B {C,D,E} F

解释:我们尝试在循环中连续匹配受保护的块\{[\{\}\w,]+\}或仅单个字符\w,如果匹配,则将其从原始字符串中删除。每次有匹配时,我们将它(意思是$1)存储在数组中,等等!

于 2012-07-27T07:24:24.183 回答
1

从 nhahtdh 的答案改进。

$_ = "A,B,{C,D,E},F";
while ( m/(\{.*?\}|((?<=^)|(?<=,)).(?=,|$))/g ) {
    print "[$&]\n";
}

再次改进它。请看这个!

$_ = "A,B,{C,D,{E,F}},G";
while ( m/(\{.*\}|((?<=^)|(?<=,)).(?=,|$))/g ) {
    print "$&\n";
}

它会得到:

A
B
{C,D,{E,F}}
G
于 2012-07-27T10:28:57.257 回答
0

这是 bash 中的正则表达式:

chronos@localhost / $ echo "A,B,{C,D,E},F" | grep -oE "(\{[^\}]*\}|[A-Z])"
A
B
{C,D,E}
F
于 2012-07-27T07:23:55.900 回答
0

试试这个正则表达式。使用正则表达式匹配并提取令牌。

/(\{.*?\}|(?<=,|^).*?(?=,|$))/

我没有在 Perl 中测试过这段代码。

这里有一个关于正则表达式引擎如何工作的假设(我假设它会\{.*?\}在第二部分之前尝试匹配第一部分)。我还假设没有嵌套的大括号,也没有成对的大括号。

于 2012-07-27T07:25:08.227 回答
-2
$s = "A,B,{C,D,E},F";
@t = split /,(?=.*{)|,(?!.*})/, $s;
于 2012-07-27T07:59:25.663 回答