6
\$\begingroup\$

I want to extract the file content into chunks with perl. I have prepared some code snippets which read a file content into chunks. I want to know what is the best way in Perl?

Example-File-Content:

1111
2222
3333
4444
5555
6666
7777
8888
9999
1212
1313
1414
1515

Example1:

#!/usr/bin/env perl
use strict;
use warnings;

open my $fh, '<', 'DUMP' or die $!;

until(grep !defined, my @chunk = map scalar <$fh>, 1 .. 4) {
    print @chunk, "\n";
}

Output:

1111
2222
3333
4444

5555
6666
7777
8888

9999
1212
1313
1414

Example2:

#!/usr/bin/perl -w
use strict;

open my $fh, '<', 'DUMP' or die $!;

my $i;
my @details;

while(<$fh>) {
    push @details, $_;
    next if ++$i % 4;
    print @details, "\n";
    @details = ();
}

Output:

1111
2222
3333
4444

5555
6666
7777
8888

9999
1212
1313
1414

Example3:

#!/usr/bin/perl -w
use strict;

open my $fh, '<', 'details.txt' or die $!;

sub read_lines {
    my ($fh, $amnt) = @_;
    return unless defined(my $line = <$fh>);
    return (
        $line,
        $amnt > 1 ? read_lines($fh, $amnt - 1) : ()
    );
}

while(my @details = read_lines($fh, 4)) {
    print @details, "\n";
}

Output:

1111
2222
3333
4444

5555
6666
7777
8888

9999
1212
1313
1414

1515
\$\endgroup\$
  • \$\begingroup\$ I've rolled back the last edit, since it appears to have been made in response to received answers. If you want iterative feedback, please make a new question - see help/someone-answers for all the details \$\endgroup\$ – Mathieu Guindon May 16 '17 at 14:23
4
\$\begingroup\$

IMHO, the best way is the second example, but with some improvements:

#!/usr/bin/perl
use strict;
use warnings;

open my $fh, '<', 'DUMP' or die $!;
while(<$fh>) {
    print $_;
    print "\n" unless $. % 4;
}

There're no needs to temporary store in an array, and use the $. variable instead of a counter.

$. contains the current line number for the last filehandle accessed, see perlvar

If you want a separte function that returns the chunck:

#!/usr/bin/perl
use strict;
use warnings;

sub getChunck {
    my $file = shift;
    my @chunck;
    open my $fh, '<', $file or die "Unable to open '$file': $!";
    while(<$fh>) {
        push @chunck, $_;
        push @chunck, "\n" unless $. % 4;
    }
    return @chunck;
}

my @chunck = getChunck('DUMP');
\$\endgroup\$
  • \$\begingroup\$ First Thanks for your answer. How you write this code snippet in an seperate functions which returns the chunk (Idee from Python generator). \$\endgroup\$ – Patrick85 May 15 '17 at 11:55
  • 1
    \$\begingroup\$ @Patrick85: See my edit. \$\endgroup\$ – Toto May 15 '17 at 12:05
  • \$\begingroup\$ Your first solution doesn't really read 4-line chunks. Rather, I would say that it prints chunked output. \$\endgroup\$ – 200_success May 15 '17 at 14:01
  • \$\begingroup\$ @Toto: Thanks for your edit :) I have one more question and maybe you could help me. What is the best way to read an file with chunks, but not return an array with all chunks rather read some data execute the data and read the other data. Like the concept in python with "generators". Is it possible you change this function to an generator-function? Many thanks in advance. \$\endgroup\$ – Patrick85 May 16 '17 at 6:11
  • \$\begingroup\$ @Patrick85: Sorry, I don't know how it works with Python, so I'm unable to transpose that in Perl. You may ask the question on stackoverflow. \$\endgroup\$ – Toto May 16 '17 at 7:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.