Foreach循环仅作用于数组中第一个元素的一部分

时间:2016-02-07 22:15:45

标签: arrays regex perl foreach

我在目录中有五个fasta文件,我可以将其成功放入一个数组中。当我尝试通过foreach循环连续打开所有文件时,要对每个文件执行正则表达式,只有目录中的第一个文件似乎打开进行处理。此外,当我尝试在第一个文件中打印整个序列时(通过未显示的诊断打印语句),忽略序列的前半部分。仅打印序列的后一部分。如果有人对如何克服这个问题有所了解,我将非常感激。这是我的代码到目前为止的样子。

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

my $dir = ("/Users/roblogan/Documents/FakeFastaFilesAgain");  
my @TrimmedSequences; 

my @ArrayofFiles = glob "$dir/*"; 

#print join("\n", @ArrayofFiles), "\n";      # this is a diagnostic test print statement

foreach my $file (@ArrayofFiles){ 
    open (my $sequence, '<', $file) or die $!; # open each file in the array
    while (my $line = <$sequence>) {  
        $line =~ s/\R//g;                          # get rid of new line breaks
        if ($line =~ m/(CTCCCA)[TAGC]+(TCAGGA)/) { # search file contents 
            push(@TrimmedSequences, $line);        # push the match into another array 
            close $file; 
        }
    }
}   

print join("\n", @TrimmedSequences), "\n"; 

2 个答案:

答案 0 :(得分:1)

在删除close语句时,测试代码(或类似代码)可以正常工作。使用关闭会在找到匹配后立即中断循环。每个文件只留下一个结果。

另请注意,您根本不需要致电关闭。当变量$ sequence失去范围时,文件将被关闭。

应该使用

chomp来摆脱换行符

这是我的测试代码。请注意一些编辑。

#!/usr/bin/perl

use strict;
use warnings;

my $files = (".");

my @files = grep { $_ =~ /\.pl/} glob "$files/*"; #added to filter out the directies in test directory, can be ignored
my @lines;

#use for in perl not foreach
for my $file (@files){
  open my $fh, '<', $file or die $!;
  while(my $line = <$fh>){
    chomp($line); #Use chomp to remove newlines
    if($line =~ /use/){
      push @lines, $line; #no need to call close at all, the filehandle is closed when it loses scope
    }
  }
}

print join("\n", @lines) . "\n";

在我的测试目录中按预期执行并打印目录中的perl文件中的所有use语句。

答案 1 :(得分:0)

您正在使用错误的变量$file(文件名,字符串)而不是$sequence(文件的文件句柄)调用close。

此外,close调用位置错误,您正在读取循环中间关闭文件句柄。如果您确实只想在每个文件中找到第一个匹配的行,请关闭文件句柄并从while循环中断(last)。如果要在所有文件中找到所有匹配的行:

foreach my $file (@ArrayofFiles){ 
    open (my $sequence, '<', $file) or die $!;
    while (my $line = <$sequence>) {  
        $line =~ s/\R//g;
        if ($line =~ m/(CTCCCA)[TAGC]+(TCAGGA)/) {
            push(@TrimmedSequences, $line);
        }
    }
    close $sequence or die $!; 
}