in reply to expanding the functionality of split

Everyone else used a loop for the "sequence of one-time delimiters" spec - but I think a different approach has more merit in this case:
#!/usr/bin/perl -wl use strict; sub msplit { my ($delim, $str) = @_; my $pat = ''; $pat = "(?>(.*?)$_$pat)?" for reverse @$delim; grep defined, $str =~ /^$pat(.+)/; } print for map "'$_'", msplit [qw(: :: \s+)], "a:b::c d"; __END__ 'a' 'b' 'c' 'd'
Update: fixed - needed nested brackets to abort looking for another field after a delimiter has failed to match.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re: Re: expanding the functionality of split
by BrowserUk (Patriarch) on Dec 10, 2002 at 19:03 UTC

    Didn't you just trade one loop for two?

    One to build the regex, one to remove the null captures made by the regex?

    Why does this have "more merit"?


    Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
    Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
    Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
    Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      You're right. I prefer this approach as it lets perl do the job of building and keeping track of the list internally - that's what "more merit" was referring to. The original version of this approach did not have the grep, and I didn't think about the fact I was introducing a second loop when I added it.

      I tried to get rid of it as follows:

      #!/usr/bin/perl -wl use strict; sub msplit { my ($delim, $str) = @_; my $pat; ### $pat = q/ (?> (.*?) (??{ shift @$delim }) (??{ $pat }) )? /; ### U +PDATE: WRONG $pat = q/ (?> (.*?) $$delim[0] (??{ shift @$delim; $pat }) )? /; $str =~ /^ $pat (.+) /x; } print for map "'$_'", msplit [qw(: :: \s+)], "a:b::c d";

      I like this version even better as it should be even more economical: the first failed match bails out of the pattern so it does not do any more work on building the regex than necessary.

      Unfortunately Perl complains about the lack of use re 'eval'; even if I add it. I'm not quite sure as to what's missing.. Maybe one of our resident regex spell casters can enlighten me?

      Makeshifts last the longest.

        I admit it, I can't see how this would work? Wouldn't you at least need /g to make this produce more than one capture?

        (Said, with the distinct feeling that I'm missing something very obvious or very clever:)


        Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
        Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
        Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
        Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.