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

I think I may have somehow broken my version of Perl. I am trying to use the split ( ) command to split a phrase into multiple parts, but I keep getting errors. I have tried searching every FAQ and manual I can find and I copy thier examples verbatim, but I continue to get the exact same error messages. Here is an example:

#!usr/bin/perl use warnings; use strict; my $Phrase = "Hello World"; my @Parts = split ( $Phrase );

If I run this I get:

Use of uninitialized value in split at File.pl line #.

As I have stated earlier, I get this message even when I copy and paste code from this website.

Tony

PS - Remove all of the electronic stuff from your computer before you weld on the case.

Replies are listed 'Best First'.
Re: Split ( ) is Giving Me a Splitting Headache
by bpphillips (Friar) on May 24, 2006 at 12:32 UTC
    From the manual you evidentally didn't find (perldoc) :-)
    perldoc -f split split /PATTERN/,EXPR,LIMIT split /PATTERN/,EXPR split /PATTERN/
    In your case, you're only passing in a single argument to split. Perl interprets this as /PATTERN/ and implicitly uses $_ as the EXPR. Since $_ hasn't been initialzed yet (hence the warning) nothing really happens (it's trying to split an undefined value on occurences of "Hello World").

    What you need to do (besides taking a look at the perldoc entry for split) is use the two-argument usage of split:
    my $Phrase = "Hello World"; my @Parts = split(/ /, $Phrase); # split $Phrase on spaces


    -- Brian
Re: Split ( ) is Giving Me a Splitting Headache
by rhesa (Vicar) on May 24, 2006 at 12:32 UTC
    split takes a pattern as first argument, so your code doesn't do what you think. See split for details.

    What you probably want is

    my @Parts = split ' ', $Phrase;
    .

    Update: Also, note the subtle difference between split / / and split ' '. The latter is "magical" in that it drops leading whitespace, splits on runs of spaces instead of a single space. The following may demonstrate:

    my $s = ' a b c '; my @p = split ' ', $s; print map { ">$_< " } @p; my @q = split " ", $s; print map { ">$_< " } @q; my @r = split / /, $s; print map { ">$_< " } @r; my @s = split /\s+/, $s; print map { ">$_< " } @s; __END__ >a< >b< >c< >a< >b< >c< >< >< >< >a< >< >< >< >< >b< >< >< >c< >< >a< >b< >c<
Re: Split ( ) is Giving Me a Splitting Headache
by Zaxo (Archbishop) on May 24, 2006 at 12:32 UTC

    You're missing the first argument, what to split on,

    my @Parts = split(" ", $Phrase );
    Your usage was not wrong; it attempted to split $_ on $Phrase, most likely putting $_ into $Parts[0].

    I don't see where the uninitialized value warning is coming from. Perhaps before posting you trimmed away the part that really initializes $Phrase. [rhesa++]

    After Compline,
    Zaxo

      $_ is undefined.
Re: Split ( ) is Giving Me a Splitting Headache
by blazar (Canon) on May 24, 2006 at 12:44 UTC

    In addition to the good answers you already got, which I recommend you to read carefully to understand what's going on, you can get what you want with a syntax similar to yours with a slight abuse of map:

    my @Parts = map split, $Phrase;

    I recommend that you do not cargo-cult this usage though, and postpone adopting it to when you will understand exactly what's going on in it too. Also because this doesn't really buy you anything that split basic usage as in rhesa's example won't.

    While we're there, one more warning: you must have noticed that people here suggested using a string contining a single space as a first argument. Notice that this is a special case, which is supposed to what you want - because it's in fact what often people want, which in turn is the reason why it's the default. But in general split expects a proper pattern as a first argument. If you give it a string, then it will be automatically converted. It is generally recommended that you use a real pattern instead.

      What's the reasoning behind that general recommendation? From your description, it appears that splitting on 'foo' and /foo/ (or even on $bar, if $bar eq 'foo') would be equivalent, so why prefer the pattern version?

      (My current practice is to use 'foo' on the principle of never using regexes where a simple comparison is sufficient. On the surface, at least, it seems that splitting on /foo/ is the same manner of overkill as using if $bar =~ /^foo$/ instead of if $bar eq 'foo'.)

        What's the reasoning behind that general recommendation? From your description, it appears that splitting on 'foo' and /foo/ (or even on $bar, if $bar eq 'foo') would be equivalent, so why prefer the pattern version?

        Because the documentation says

        split /PATTERN/,EXPR,LIMIT split /PATTERN/,EXPR split /PATTERN/ split

        In fact splitting on 'foo' and /foo/ are (currently) equivalent because perl converts the string to a regex:

        perl -MO=Deparse -ne 'split "foo"' LINE: while (defined($_ = <ARGV>)) { split(/foo/, $_, 0); } -e syntax OK

        Who knows? I doubt it, but the docs do not specify what should happen with generic strings other than ' ' and maybe one day special behaviour may be implemented for them along the lines of what is currently available for ' '.

        (My current practice is to use 'foo' on the principle of never using regexes where a simple comparison is sufficient. On the surface, at least, it seems that splitting on /foo/ is the same manner of overkill as using if $bar =~ /^foo$/ instead of if $bar eq 'foo'.)

        Your principle is based on an assumption that is simply not true for as we've seen before, your string is converted to a regex anyway. And OTOH matches like /foo/ are internally optimized to basically do an index. So no overkill. If you don't trust me, just trust B::Concise:

        $ perl -MO=Concise -pe '$_=split "foo"' >1.txt -e syntax OK $ perl -MO=Concise -pe '$_=split /foo/' >2.txt -e syntax OK $ diff [12].txt 20c20 < 6 </> pushre(/"foo"/) s*/64 ->7 --- > 6 </> pushre(/"foo"/) s/64 ->7

        Notice that the only difference is an asterisk, which means "Do something weird for this op".

        I'm not saying that I don't agree with you on the $bar =~ /^foo$/ vs. $bar eq 'foo' issue. Because I do agree. (Also because they're not strictly equivalent:

        $ perl -le 'print "bar\n" =~ /^bar$/ ? "ok" : "not ok"' ok

        and people happen to use the former whereas they really want the latter.) Simply, that's not the same for split's first argument.

Re: Split ( ) is Giving Me a Splitting Headache
by vkroll (Novice) on May 24, 2006 at 16:30 UTC
    You should read perldoc -f split
    #!usr/bin/perl use warnings; use strict; my $Phrase = "Hello World"; my @Parts = split(/\s/, $Phrase) ;
    ## this works
    Volker Kroll -- Seeker of Wisdom in the perl of programminglanguages Berlin -- Germany
Re: Split ( ) is Giving Me a Splitting Headache
by BigRare (Pilgrim) on May 24, 2006 at 14:57 UTC
    PS - Remove all of the electronic stuff from your computer before you weld on the case.

    I see... This explains everything...
Re: Split ( ) is Giving Me a Splitting Headache
by tcf03 (Deacon) on May 25, 2006 at 10:44 UTC
    OK Im a little confused now - I see where and why he is getting his error above and that $_ is undefined. In my example below - I see the first print statement which I beleive to be equivelant to the ops print statement. But Im confused about my second print statement - where and how is $_ getting set? Is split setting it?

    from perldoc -f split:
    If EXPR is omitted, splits the $_ string. If PATTERN is also omitted, + splits on whitespace (after skipping any leading whitespace). Anyth +ing matching PATTERN is taken to be a delimiter separating the fields +. (Note that the delimiter may be longer than one character.)
    EXPR is not omitted, PATTERN is not omitted - where is $_ coming from? Is there some documentation someone can point out that explains this behavior?
    #!/usr/bin/perl use warnings; use strict; print "$_\n" for split ( "Hello World" ); print "$_\n" for split /\s+/, "Hello World";

    UPDATE
    OK I see in perlvar that for is setting it and split is not my culprit.
    Here are the places where Perl will assume $_ even if you don't use it +: __snip__ - The default iterator variable in a foreach loop if no other variable + is supplied.
    But why is for not setting it in the first print statement?

    UPDATE #2
    from the following looks like $_ is an empty hash?
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; print "\n\n"; print "\$_ = $_\n"; print "\n\n"; for ( 1 .. 10 ) { print "\$_ = $_\n" } print "\n\n"; print $_ for {}; print "\n\n"; print Dumper $_ for {}; print "\n\n"; my $count = 0; for ( sort keys %{ $_ } ) { print $count++, ":$_{$_} $_\n" };

    Now Im really confused.
    Ted
    --
    "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
      --Ralph Waldo Emerson
      The key here is what happens when you perform the incorrect usage of split:
      my @parts = split( "Hello World" ); # generates warning print "Parts: " . scalar(@parts) . "\n"; # prints "Parts: 0" for( @parts ){ # never enters this loop since the array is empty print "$_\n"; }
      The warning you saw on your first loop was generated by the split statement, not the print statement. As demonstrated above, the print statement never gets executed because the loop is never entered.

      Hope that helps make some sense of what's happening,
      -- Brian
Re: Split ( ) is Giving Me a Splitting Headache
by mattr (Curate) on May 25, 2006 at 13:01 UTC
    Read the above comments and if you can't get perldoc working on your machine's text terminal then you can read the split manual page here.

    Myself I don't think I have ever used split without the two slashes, though it strikes me that if you use a scalar as a split pattern without putting it into slashes like
    split($pat, $stringtosplit); then I'm not sure what you'll get out of it. My guess would be it will be like using slashes, since perl tries to Do What You Mean sometimes.

    Anyway the perldoc says,

    As a special case, specifying a PATTERN of space (' ') will split on white space just as split with no arguments does. Thus, split(' ') can be used to emulate awk's default behavior, whereas split(/ /) will give you as many null initial fields as there are leading spaces. A split on /\s+/ is like a split(' ') except that any leading whitespace produces a null first field. A split with no arguments really does a split(' ', $_) internally.

Re: Split ( ) is Giving Me a Splitting Headache
by zakame (Pilgrim) on May 29, 2006 at 14:53 UTC
    You could do this:
    $phrase = "Hello World"; for ($phrase) { @parts = split }
    Or this, from a filehandle:
    while (<STDIN>) { push @parts, split; }
Re: Split ( ) is Giving Me a Splitting Headache
by Anonymous Monk on May 25, 2006 at 09:28 UTC
    split (/ /, $Phrase );