Rob Rob - 4 months ago 7
Perl Question

After successfully using grep on a variable it prints blank

I am opening a directory that has files that look like the following. Here is one file:

>UVWXY
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>STUVW
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>QRSTU
ABCDEFGHIJKLMNOPQRSTUVWXYZ


Here is a second file:

>EFGHI
ABCDEFGHIJKLMNOPQRSTUVWXYZ


Here is my code:

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

my ($directory) = @ARGV;
my $dir = "$directory";
my @ArrayofFiles = glob "$dir/*";

open(OUT, ">", "/path/to/output.txt") or die $!;

foreach my $file(@ArrayofFiles){
open(my $fastas, $file) or die $!;
my $numberoffastas = grep{/>/}<$fastas>;
#print $numberoffastas, "\n";
while (my $line = <$fastas>){
print $line, "\n";
}
}


Nothing is printed out for $line, but this code correctly counts the number of ">"s that appear in the file when it is opened, evidenced by printing $numberoffastas.

How can I fix this code so that $line = something like:

>EFGHI


or

ABCDEFGHIJKLMNOPQRSTUVWXYZ


Thanks

mob mob
Answer
my $numberoffastas = grep{/>/}<$fastas>;

calls readline on the $fastas filehandle in list context, which consumes all the input on the filehandle. At your subsequent call in while (my $line = <$fastas>), there is no more input on that filehandle to provide, and the while condition fails.

Save the inputs in an array and perform both operations on the array

my @inp = <$fastas>;
my $numberoffastas = grep {/>/} @inp;
...
foreach my $line (@inp) {
   ...
}

or if you are worried that the files are too large and will give you memory headaches, reopen the file

my $numberoffastas = grep {/>/} <$fastas>;
close $fastas;
open $fastas, $file;
...
while (my $line = <$fastas>) { ... }

or seek to the beginning of the file

open my $fastas, '+<', $file;    #   +<  means random-access mode
my $numberoffastas = grep {/>/} <$fastas>;
...
seek $fastas, 0, 0;              #   rewind to beginning of file
while (my $line = <$fastas>) { ... }