Sprad has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to parse a string where the comma is pulling double duty. Here's an example:

foo:a,bar:a,b,c,baz:d

This should result in the following array, which I can then process further as needed:

foo:a bar:a,b,c baz:d

I could do this with a two-pass method, where first I do a substitution like this:

s/,(\w+):/MONKEYBUTT$1:/g;

and then split on /MONKEYBUTT/ (or some other unlikely string).

But is there a more elegant solution that wouldn't offend our simian friends?

---
A fair fight is a sign of poor planning.

Replies are listed 'Best First'.
Re: Double-duty commas
by Jasper (Chaplain) on Feb 25, 2005 at 17:30 UTC
     split/,(?=\w+:)/
Re: Double-duty commas
by ikegami (Patriarch) on Feb 25, 2005 at 17:33 UTC

    /(\w+):(\w+(?:,\w+)*)(?:,|$)/g does the trick, as seen here:

    use Data::Dumper; $_ = 'foo:a,bar:a,b,c,baz:d'; my %data; while (/(\w+):(\w+(?:,\w+)*)(?:,|$)/g) { my $key = $1; my @vals = split(/,/, $2); $data{$key} = \@vals; } # Alternative # =========== # # foreach (split(/,(?=\w+:)/)) { # my ($key, $val) = split(/:/, $_, 2); # my @vals = split(/,/, $val); # $data{$key} = \@vals; # } print(Dumper(\%data)); __END__ output ====== $VAR1 = { 'foo' => [ 'a' ], 'baz' => [ 'd' ], 'bar' => [ 'a', 'b', 'c' ] };
Re: Double-duty commas
by Enlil (Parson) on Feb 25, 2005 at 17:34 UTC
    If trailing commas (on each line) would not an issue this might work for what you are doing:
    #!/usr/bin/perl -w use strict; use warnings; $_ = 'foo:a,bar:a,b,c,baz:d,faa:this,is,great'; my @array = m/(\w+:(?:(?>\w+,?)+)(?!:))/g; print $_,$/ for @array; __END__ foo:a, bar:a,b,c, baz:d, faa:this,is,great

    update: Re: Double-duty commas is much more elegant

Re: Double-duty commas
by Fletch (Bishop) on Feb 25, 2005 at 18:07 UTC

    Not a direct solution, but \0 makes a very good unlikely string (unless you're primate-arily dealing with binary data . . .).