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

Hi monks,
Given a string ABC"123"XYZ, I want to split it into AAA, "123", XYZ. So here snippet go:
my $str = "ABC\"123\"XYZ"; my @p = split /(?<!\")(?=\".*\")|(?<=\".*\")(?!\")/, $str; foreach my $part (@p) { print "part = ($part)\n"; } __error__ Variable length lookbehind not implemented before HERE mark in regex m +/(?<!")(?=".*")|(?<=".*")(?!") << HERE /
I have no idea what happen, please advise. Thanks ^_^

Replies are listed 'Best First'.
Re: Look Behind not work, please help
by jmcnamara (Monsignor) on Apr 30, 2003 at 08:34 UTC

    Perhaps a simple negated character class and capture might work just as well:
    #!/usr/bin/perl -w use strict; my $str = 'ABC"123"XYZ'; my @p = split /("[^"]+")/, $str; foreach my $part (@p) { print "part = ($part)\n"; } __END__ Prints: part = (ABC) part = ("123") part = (XYZ)

    --
    John.

      That's an interesting technique.

      The split() call normally captures everything that doesn't match the regex; in this case, it's the unquoted parts. You add on a capture in the regex, which tells split to also keep the separators; in this case, it's the quoted parts. The non-obvious part is that split will interleave the captures-in-separators and the usual non-separator portions properly.

      --
      [ e d @ h a l l e y . c c ]


        Yes, it is one of the many interesting features of split, from the pod:
        If the PATTERN contains parentheses, additional list elements are created from each matching substring in the delimiter. split(/([,-])/, "1-10,20", 3); produces the list value (1, '-', 10, ',', 20)

        Other interesting features of split are LIMIT, negative LIMIT, the parameter-less split, the difference between ' ', / / and /\s+/ and the implicit split to @_ when not in a list context (which is very useful in Golf).

        I used one of these features in Strip leading and trailing whitespace from a string..

        --
        John.

Re: Look Behind not work, please help
by Anonymous Monk on Apr 30, 2003 at 15:18 UTC
    Nobody explained the error. Allow me.

    Part of your RE was a lookbehind to see that you weren't preceeded by \".*\". Finding that might take searching back 5 characters or 50. Getting that logic right is hard, and it has never been implemented in Perl. Therefore you can only do a lookbehind when Perl can figure out exactly how many characters back it has to go.

    (Just to annoy people, Java has no such limit.)

Re: Look Behind not work, please help
by nite_man (Deacon) on Apr 30, 2003 at 09:02 UTC
    Another way:
    my $str = "ABC\"123\"XYZ"; $str =~ /([A-Z]*)"([0-9]*)"([A-Z]*)/; print "Res: $1 $2 $3\n" __DATA__ Res: ABC 123 XYZ
          
    --------------------------------
    SV* sv_bless(SV* sv, HV* stash);
    
      This is update my previous post!
      my $str = "ABC\"123\"XYZ"; map { print $_ . "\n" } split('"', $str); __DATA__ ABC 123 XYZ
            
      --------------------------------
      SV* sv_bless(SV* sv, HV* stash);