Divide by comma, but only if not in brackets

I am trying to do a comma delimited string

my $string='ab,12,20100401,xyz(A,B)'; my @array=split(',',$string); 

If I split as above, the array will have values

 ab 12 20100401 xyz(A, B) 

I need the values ​​as shown below.

 ab 12 20100401 xyz(A,B) 

(do not divide xyz (A, B) into 2 values) How to do this?

+6
split perl
source share
6 answers
 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*//; } } 

It supports:

  • nested parentheses;
  • empty field;
  • strings of any length.
+4
source share

Here is one way that should work.

 use Regexp::Common; my $string = 'ab,12,20100401,xyz(A,B)'; my @array = ($string =~ /(?:$RE{balanced}{-parens=>'()'}|[^,])+/g); 

Regexp :: Common can be installed from CPAN.

There is an error in this code emanating from the depths of Regexp :: Common. Be warned that this (unfortunately) does not correspond to the lack of space between ,, .

+3
source share

Limit the number of elements that can be divided into:

 split(',', $string, 4) 
+1
source share

Here's another way:

 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); 

It produces:

 ab 12 20100401 xyz(A,B) 
0
source share

Here is my attempt. It should handle depth well and can even be extended to easily include other characters in square brackets (although it's even harder to make sure they are MATCHES). This method will not work for quotes at all, and not for brackets.

 #!/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; } 
0
source share

Well, an old question, but I just had to struggle with it all night, and there was never an answer to the question, so if someone comes here Google, like me, that's what I finally got. This is a very short answer using only the built-in PERL regular expression functions:

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

Commas that are not included in parentheses are changed to new lines, and then arrays are divided into them. This will ignore the commas inside any level of nested parentheses if they are correctly balanced with the appropriate number of open and closed pairs.

It is assumed that in the initial value of $ string there will be no newline characters \n . If you need to either temporarily replace them with something else in front of the lookup line, then use a loop to replace after split or just select another separator to split the array.

0
source share

All Articles