programminglearner
programminglearner

Reputation: 542

Perl nested foreach loop on an array of filehandles

I want to print out the second column of two files. Eventually I'm going to print it into another file but right now I just want to output it to the terminal. I tried doing this by making an array of the two files. Here is my code, but it returns nothing.

unless (open COL1, '<'. $file1) {die "Couldn't open '$file1'\n";}
unless (open COL2, '<'. $file2) {die "Couldn't open '$file2'\n";}
while (!eof(COL1) and !eof(COL2)) {
    my @line = [<COL1>, <COL2>];
    #my $line2 = <COL2>;
    foreach my $line (@line) {
            foreach my $row ($line){
    my @column2 = split( /\t/, $row);
    print $column2[1];
}
  }
}
  close COL1;
    close COL2;

If I do the inner for loop for only a single file it works fine. Here is my code for a single file:

unless (open COL1, $file1) {die "\nUnable to open '$spare_f2;\n";}
foreach my $row (<COL1>) {
    my @column2 = split( /\t/, $row);
    print $column2[1];
}
close COL1;

A dirty fix would be to just copy paste the same code and do it for the second file, but I would like to have it working with an array so a single foreach loop can handle them both.

Upvotes: 1

Views: 229

Answers (1)

choroba
choroba

Reputation: 241848

You assigned a single element to the array @line, an array reference to the contents of the two files.

my @line = [<COL1>, <COL2>];

You probably wanted

my @line = (scalar <COL1>, scalar <COL2>);

i.e. assign one line from the first handle, and one line from the second handle.

The full program would look like

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

open my $in1, '<', shift or die $!;
open my $in2, '<', shift or die $!;

until (eof $in1 || eof $in2) {
    my @lines = (scalar <$in1>, scalar <$in2>);
    chomp @lines;
    my @columns;
    for my $line (@lines) {
        push @columns, (split /\t/, $line)[1];
    }
    say join "\t", @columns;
}

The body of the loop can be shortened by using map instead of a for loop:

chomp( my @lines = (scalar <$in1>, scalar <$in2>) );
say join "\t", map +(split /\t/, $_)[1], @lines;

Upvotes: 3

Related Questions