在逗号上拆分,但仅在不在括号中时

时间:2011-02-19 06:50:00

标签: perl split

我正在尝试使用逗号分隔符

对字符串进行拆分
my $string='ab,12,20100401,xyz(A,B)';
my @array=split(',',$string);

如果我如上所述进行拆分,则数组将具有值

ab
12
20100401
xyz(A,
B)

我需要以下价值观。

ab
12
20100401
xyz(A,B) 

(不应将xyz(A,B)拆分为2个值) 我该怎么做?

6 个答案:

答案 0 :(得分:4)

use Text::Balanced qw(extract_bracketed);
my $string = "ab,12,20100401,xyz(A,B(a,d))";
my @params = ();
while ($string) {
    if ($string =~ /^([^(]*?),/) {
        push @params, $1;
        $string =~ s/^\Q$1\E\s*,?\s*//;
    } else {
        my ($ext, $pre);
        ($ext, $string, $pre) = extract_bracketed($string,'()','[^()]+');
        push @params, "$pre$ext";
        $string =~ s/^\s*,\s*//;
    }
}

这支持:

  • 嵌套括号;
  • 空白字段;
  • 任意长度的字符串。

答案 1 :(得分:3)

这是一种应该有效的方法。

use Regexp::Common;

my $string = 'ab,12,20100401,xyz(A,B)';
my @array = ($string =~ /(?:$RE{balanced}{-parens=>'()'}|[^,])+/g);
可以从CPAN安装

Regexp::Common

此代码中存在一个错误,来自Regexp :: Common的深度。请注意,(遗憾的是)这将无法与,,之间的空间不足相匹配。

答案 2 :(得分:1)

限制可拆分的元素数量:

split(',', $string, 4)

答案 3 :(得分:0)

这是另一种方式:

my $string='ab,12,20100401,xyz(A,B)';
my @array = ($string =~ /(
    [^,]*\([^)]*\)   # comma inside parens is part of the word
    |
    [^,]*)           # split on comma outside parens
    (?:,|$)/gx);

产地:

ab
12
20100401
xyz(A,B)

答案 4 :(得分:0)

这是我的尝试。它应该很好地处理深度,甚至可以扩展到容易包括其他括号内的符号(虽然更难以确定它们匹配)。这种方法通常不适用于引号而不是括号。

#!/usr/bin/perl

use strict;
use warnings;

my $string='ab,12,20100401,xyz(A(2,3),B)';

print "$_\n" for parse($string);

sub parse {
  my ($string) = @_;
  my @fields;

  my @comma_separated = split(/,/, $string);

  my @to_be_joined;
  my $depth = 0;
  foreach my $field (@comma_separated) {
    my @brackets = $field =~ /(\(|\))/g;
    foreach (@brackets) {
      $depth++ if /\(/;
      $depth-- if /\)/;
    }

    if ($depth == 0) {
      push @fields, join(",", @to_be_joined, $field);
      @to_be_joined = ();
    } else {
      push @to_be_joined, $field;
    }
  }

  return @fields;
}

答案 5 :(得分:0)

好吧,老问题,但我刚刚碰巧整晚都在摔跤,这个问题从来没有得到过回答,所以如果有人像我一样到谷歌来这里,这就是我最终得到的。仅使用内置的PERL正则表达式功能,这是一个非常简短的答案:

my $string='ab,12,20100401,xyz(A,B)';
string =~ 's/((\((?>[^)(]*(?2)?)*\))|[^,()]*)(*SKIP)([,])/$1\n/g';
my @array=split('\n',$string);

不在括号内的逗号更改为换行符,然后将数组拆分为它们。这将忽略任何级别的嵌套括号内的逗号,只要它们与匹配数量的打开和关闭的parens正确平衡即可。

这假设您在$ string的初始值中不会有换行符\n。如果需要,可以在替换行之前用其他东西临时替换它们,然后在split之后使用循环替换回来,或者只选择一个不同的分隔符来拆分数组。