spz1st has asked for the wisdom of the Perl Monks concerning the following question:
I need to split a string on the pattern of '),(', but have not been successful so far.
$str = '(1,"(text)", 123),(2,"(string)", 234),(...)';
@arr = split(/),(/, $str); # fail
@arr = split(/\),\(/, $str); # fail
I've tried several other ways I can think of, but all failed.
Re: split on the pattern of '),('
by kennethk (Abbot) on Jun 07, 2012 at 19:47 UTC
|
If you need to escape characters in a regular expression, you can reliably use either the quotemeta function or the delimiters \Q and \E, as described in Quote and Quote like Operators. For example, you would successfully split with
my @arr = split /\Q),(\E/, $str;.
On examining your input, it's possible you'll get more mileage from either a state machine character-wise parser, a regular expression, or my favorite in this context, multiple operations including a different basic split. Since you appear to be separating tuples, you could use
my @arr = split /(?<=\))\s*,\s*(?=\()/, $str; to separate the tuples, and then deal with each one individually.
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: split on the pattern of '),('
by snape (Pilgrim) on Jun 07, 2012 at 20:13 UTC
|
my @arr = split(/\),\(/, $str);
I have used strict and warnings and here is my entire code. It also works if you didn't use strict or warnings.
#!/tools/bin/perl
use strict;
use warnings;
my $str = '(1,"(text)", 123),(2,"(string)", 234),(...)';
my @arr = split(/\),\(/, $str);
for(my $i = 0; $i<= $#arr; $i++){
print $arr[$i],"\n";
}
exit;
##### OUTPUT ####
(1,"(text)", 123
2,"(string)", 234
...)
Try running the above code
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: split on the pattern of '),('
by ikegami (Patriarch) on Jun 07, 2012 at 21:23 UTC
|
Assuming nesting (e.g. (3,(4,5),6)) can't happen,
my @recs = $recs =~ /
\G
\(
( (?: [^()"] | "[^"]*" )* )
\)
(?: , | \Z )
/xg;
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
my $string = "(foo),(bar),(baz)";
my @parts = split m{ [)] [,] [(] }x, $string;
print "GOT: $_\n" for @parts;
Instead of m{ [)] [,] [(] }x you could use m{ \) , \( }x ... whichever you think is most readable. Either way, try to avoid the appearance of a million toothpicks standing on end.
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
$str = '(1,"(text),(text)", 123),(2,"(string)", 234),(...)';
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
Re: split on the pattern of '),('
by Anonymous Monk on Jun 07, 2012 at 19:36 UTC
|
| [reply] [Watch: Dir/Any] |
|
#!/usr/bin/perl --
use strict; use warnings;
use Text::CSV;
use Data::Dump;
my $str = '(1,"(text)", 123),(2,"(string)", 234),(...)';
my $csv = Text::CSV->new( {
quote_char => '"',
sep_char => ',',
allow_loose_escapes => 1,
empty_is_undef => 1,
binary => 1,
auto_diag => 1,
} );
$csv->parse( $str );
dd [ $csv->fields() ];
__END__
["(1", "(text)", " 123)", "(2", "(string)", " 234)", "(...)"]
| [reply] [Watch: Dir/Any] [d/l] |
Re: split on the pattern of '),('
by AnomalousMonk (Archbishop) on Jun 08, 2012 at 07:39 UTC
|
| [reply] [Watch: Dir/Any] |
|
|