Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

split on the pattern of '),('

by spz1st (Initiate)
on Jun 07, 2012 at 19:23 UTC ( [id://975022]=perlquestion: print w/replies, xml ) Need Help??

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.

Replies are listed 'Best First'.
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.

Re: split on the pattern of '),('
by snape (Pilgrim) on Jun 07, 2012 at 20:13 UTC

    I don't know why it is not working for you but piece of code below works for me

    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

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;
      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'
        That fails for
        $str = '(1,"(text),(text)", 123),(2,"(string)", 234),(...)';
Re: split on the pattern of '),('
by Anonymous Monk on Jun 07, 2012 at 19:36 UTC

      It is "workable" but kinda meh

      #!/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)", "(...)"]
Re: split on the pattern of '),('
by AnomalousMonk (Archbishop) on Jun 08, 2012 at 07:39 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://975022]
Approved by Perlbotics
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-03-29 10:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found