Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Split on every second character

by gri6507 (Deacon)
on Feb 12, 2010 at 22:56 UTC ( [id://822947]=perlquestion: print w/replies, xml ) Need Help??

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

I have what I thought would be a very simple problem. However, it has me baffled. I have data of the form
"010203040506"
which I would like to split into the form of
"01 02 03 04 05 06"
. The code that I wrote

use strict; use warnings; use Data::Dumper; my @list = split(/(..)/, '010203040506'); print Dumper(\@list); print join(' ', @list)

does the job, but produces empty elements in the list, which results in the undesired output of
" 00  01  02  03  04  05  06"
which contains unwanted spaces. I understand why this is: when splitting on any two characters, the first two are a match, thus, thus they represent the split string (which is element 1), which separates a NULL string (captured in element 0) from the remaining characters (captured in remaining characters). However, I don't want to see the extra spaces in the resulting output. How can I get rid of that?

Replies are listed 'Best First'.
Re: Split on every second character
by BrowserUk (Patriarch) on Feb 12, 2010 at 23:21 UTC

    For anything that doesn't require conditional matching, I prefer unpack:

    print for unpack '(A2)*', '010203040506';; 01 02 03 04 05 06

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Split on every second character
by linuxer (Curate) on Feb 12, 2010 at 23:00 UTC

    If you are sure that the string is even sized, you can use a simple regex like this:

    use strict; use warnings; my $string = "0102030405"; # will miss the last character when string is odd sized my @elements = $string =~ m/(..)/g; print "@elements\n";
    Update: modified code

      and if you are unsure but want the last character for odd length strings you can:

      my @list = $str =~ /(..?)/g;

      True laziness is hard work
      I didn't think of using the match operator for this. Thanks!
Re: Split on every second character
by ikegami (Patriarch) on Feb 12, 2010 at 23:06 UTC

    When you use split, the pattern must match what separates what you want. In this case, the separator is the empty string between a character at an odd positions and a character at an even position. That's not exactly straightforward to match, but it's possible.

    $ perl -E'say for split /(?!^|\z)(?(?{ pos()%2 })(?!))/, "0102030405"' 01 02 03 04 05 06

    Here, it's simpler just to match what you want grab rather than what separates them, so just use a m//g:

    $ perl -E'say for "0102030405" =~ /(..?)/sg' 01 02 03 04 05 06
      No wonder getting the split() operator to work correctly was difficult. Thank you!
Re: Split on every second character
by rubasov (Friar) on Feb 13, 2010 at 10:35 UTC
    Or still using split, you can just drop every second element from the result list:
    $ perl -le '@l = grep {$i++ % 2} split /(..)/, "010203040506"; print j +oin "|", @l'
    But the solutions provided by other monks are definitely nicer.

      I agree that some variation of an approach using  m/..?/g or  unpack() is better, but a more concise  split() solution would be:

      >perl -wMstrict -le "print for grep length, split /(..)/, '0001020304101112';" 00 01 02 03 04 10 11 12

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://822947]
Approved by broomduster
Front-paged by linuxer
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-04-25 08:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found