-3

I'm trying to split a string every 5 characters. The array I'm getting back from split isn't how I'm expecting it: all the even indexes are empty, the parts I'm looking for are on odd indexes.

This version doesn't output anything:

use warnings;
use strict;
my @ar = <DATA>;
foreach (@ar){
    my @mkh = split (/(.{5})/,$_);
    print $mkh[2];
}
__DATA__
aaaaabbbbbcccccdddddfffff

If I replace the print line with this (odd indexes 1 and 3):

 print $mkh[1],"\n", $mkh[3];

The output is the first two parts:

aaaaa
bbbbb

I don't understand this, I expected to be able to print the first two parts with this:

print $mkh[0],"\n", $mkh[1];

Can someone explain what is wrong in my code, and help me fix it?

Mat
  • 202,337
  • 40
  • 393
  • 406
mkHun
  • 5,891
  • 8
  • 38
  • 85

3 Answers3

3

The first argument in split is the pattern to split on, i.e. it describes what separates your fields. If you put capturing groups in there (as you do), those will be added to the output of the split as specified in the split docs (last paragraph).

This isn't what you want - your separator isn't a group of five characters. You're looking to split a string every X characters. For that, better use:

my @mkh = (/...../g);
# or
my @mkh = (/.{5}/g);

or one of the other options you'll find in: How can I split a string into chunks of two characters each in Perl?

Community
  • 1
  • 1
Mat
  • 202,337
  • 40
  • 393
  • 406
  • I edited my script but It is not working error of `Use of uninitialized value in print at line 5`. – mkHun Oct 19 '14 at 15:39
  • 1
    If I replace that line in your script with exactly what I have in my post, I don't get any warnings, and `ccccc` is output (without a newline). Make sure you've copied as-is. – Mat Oct 19 '14 at 15:41
  • sorry. It is working. im missed `g` global match. so it is not gives output – mkHun Oct 19 '14 at 15:45
  • @Mat Please consider editing the question since you appear to be able to understand it (i'm not). – ivan_pozdeev Oct 23 '14 at 20:19
  • @ivan_pozdeev: Is it better now? Title might need some more work... but I'm not finding anything shorter. – Mat Oct 23 '14 at 20:41
2

Debug using Data::Dump

To observe exactly what your split operation is doing, use a module like Data::Dump:

use warnings;
use strict;

while (<DATA>) {
    my @mkh = split /(.{5})/;

    use Data::Dump;
    dd @mkh;
}
__DATA__
aaaaabbbbbcccccdddddfffff

Outputs:

("", "aaaaa", "", "bbbbb", "", "ccccc", "", "ddddd", "", "fffff", "\n")

As you can see, your code is splitting on groups of 5 characters, and leaving empty strings between them. This is obviously not what you want.

Use Pattern Matching instead

Instead, you simply want to capture groups of 5 characters. Therefore, you just need a pattern match with the /g Modifier:

use warnings;
use strict;

while (<DATA>) {
    my @mkh = /(.{5})/g;

    use Data::Dump;
    dd @mkh;
}
__DATA__
aaaaabbbbbcccccdddddfffff

Outputs:

("aaaaa", "bbbbb", "ccccc", "ddddd", "fffff")
Community
  • 1
  • 1
Miller
  • 34,962
  • 4
  • 39
  • 60
1

You can also use zero-width delimiter, which can be described as split string at places which are in front of 5 chars (by using \K positive look behind)

my @mkh = split (/.{5}\K/, $_);
mpapec
  • 50,217
  • 8
  • 67
  • 127