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

Hey guys, got a real simple problem im having with split. The following code should split the string passed at the command line into chunks of two and stuff those into @vals.. Yet only the last letter and sometimes nothing is the result. What am i doing wrong? Thanks for your time.
#!/usr/bin/perl use warnings; $in = $ARGV[0]; @vals = split(/../, $in); print @vals;
foreach(@the_wicked){sleep(0);}

Replies are listed 'Best First'.
Re: Difficulties with split
by almut (Canon) on Apr 27, 2009 at 23:06 UTC

    If I'm understanding you correctly, you want

    @vals = unpack "(A2)*", $in;

      That doesn't work with strings internally encoded as UTF8 before 5.10.0 (and not at all before 5.8.0).

      If you're working with arbitrary characters, if you don't to mess with utf8::downgrade, or if you are worried about backwards compatibility, you can use the following instead:

      @vals = $in =~ /(..)/sg;
      W00t, that is indeed what i wanted, thank you almut. :)

      foreach(@the_wicked){sleep(0);}
Re: Difficulties with split
by runrig (Abbot) on Apr 27, 2009 at 23:08 UTC
    Think about it. You are splitting ON any two characters. If you were splitting on, say, a comma (","), would you expect commas to end up in the result? Some options, one, use a zero-width look behind assertion:
    split /(?<=..)/, $in; # johngg is right...bad answer
    or capture what you're splitting on, and filter out empty elements:
    grep { length($_) > 0 } split /(..)/, $in;
    or do like almut says above and use unpack :-)
      split /(?<=..)/, $in;

      I don't think that is going to do quite what you expected. It will split the string at every point that is preceded by two characters.

      $ perl -le ' -> $str = q{abcdefg}; -> @bits = split m{(?<=..)}, $str; -> print for @bits;' ab c d e f g $

      It seems that split is not perhaps the handiest tool for this task.

      Cheers,

      JohnGG

      That is a good point, i forgot split removes the delimitter heh, and should've tried capping it.

      I've never heard of a look behind assertion, it sounds interesting...

      Thanks runrig :)

      foreach(@the_wicked){sleep(0);}
Re: Difficulties with split
by jwkrahn (Abbot) on Apr 28, 2009 at 00:43 UTC

    Or you could use a regular expression to do what you want:

    my @vals = $ARGV[ 0 ] =~ /../g; print @vals;
      Don't forget about the last char in strings of odd length:
      my @vals = $ARGV[ 0 ] =~ /..|.$/g; print @vals;

        OK:

        my @vals = $ARGV[ 0 ] =~ /..?/g; print @vals;
Re: Difficulties with split
by perliff (Monk) on Apr 28, 2009 at 09:04 UTC
    my 2 cents...

    #!/usr/bin/perl use warnings; $in = $ARGV[0]; @vals = split(/\.\./, $in); print @vals;

    perliff

    ----------------------

    "with perl on my side"

      A full stop is a regular expression metacharacter meaning match any character (with caveats, see perlretut, perlre). However, a backslash escapes the special meaning of a metacharacter so that \. matches a literal full stop. That means you are spliting on two literal full stops, which is not quite what was wanted.

      $ perl -le ' > $in = q{abcdefg}; > @vals = split m{\.\.}, $in; > print for @vals;' abcdefg $ perl -le ' > $in = q{abc..defg}; > @vals = split m{\.\.}, $in; > print for @vals;' abc defg $

      I hope this is of interest.

      Cheers,

      JohnGG