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

Ouch my brain hurts! I've been trying to understand why this happens:
$string = "a:b:c"; ($line) = split /:/, $string, 0; print "Split zero times - $line\n"; ($line) = split /:/, $string, 1; print "Split one time - $line\n"; ($line) = split /:/, $string, 2; print "Split two times - $line\n"; outputs: Split zero times - a Split one time - a:b:c Split two times - a
What's going on with the second split? Is this a boundary condition bug^H^H^Hfeature in Perl, or is this migrane clouding my better judgement? Your prescriptions are very much appreciated.

Replies are listed 'Best First'.
Re: A split ing headache
by extremely (Priest) on Dec 12, 2000 at 09:41 UTC
    split /:/, $string, 0 is the same as not putting the ", 0" on the end. It isn't split zero times. The number on the end is the number of parts to split the string INTO, not how many TIMES it is split. Thus 1 gets you one part and 2 gets you qw( a b:c ). The third number is a constraint on the size of the list created by split.

    --
    $you = new YOU;
    honk() if $you->love(perl)

(take two...) Re: A split ing headache
by mwp (Hermit) on Dec 12, 2000 at 12:28 UTC
    As my esteemed colleagues have pointed out, the LIMIT argument for split doesn't truncate tokens whose indices are greater than LIMIT, merely lumps them together as the last return value. Think of it like this: split EXPR on PATTERN into a list LIMIT elements long.
    my $string = 'see:how:they:code'; my($zeroth, $first, $remainder) = split ':', $string, 3; print $zeroth, "\n", # see $first, "\n", # how $remainder, "\n"; # they:code

    If you want to actually truncate the leftover list elements, try this:</o>

    my($zeroth, $first, $second) = (split ':', $string)[0..2]; print $zeroth, "\n", # see $first, "\n", # how $second, "\n"; # they

    And 'code' just goes away. Just watch your parens, because this is wrong:

    split(':', $string)[0..2]

    Hopefully you can see why.

      I tend to use alakaboo's construct when doing this: my (@bits) = (split /:/, $thing,4)[0..2] well, except that I constrain it to one more than the slice size so it doesn't do extra work.

      When assigning to a list of scalars I use: my ($a, $b, $c) = split /:/, $thing, 4; knowing that the last item with all the unsplit bits will just blow away. No reason to promote a list to an anonymous array when you don't have to. Not a big deal tho but I've always felt that asking for 4 parts and only saving 3 made more sense.

      --
      $you = new YOU;
      honk() if $you->love(perl)

        Perl does that for automagically. split() knows how many scalars (if a finite number) you had on the left-hand side of the function call, so it will optimize itself thus.

        japhy -- Perl and Regex Hacker
Re: A split ing headache
by tilly (Archbishop) on Dec 12, 2000 at 09:11 UTC
    Try that with:
    $line = join "|", split /:/, $string, $count;
    and you will be able to see what was split and joined. Then compare with what it says in split.

    When I do it it works just like the big old book says.

    BTW you might find the following string more instructive than your current one:

    $string = 'a:b:c:::';