Perl,匹配目录的文件,使用带有部分这些文件名的数组

时间:2015-03-02 20:29:57

标签: arrays regex perl grep

所以,我这个目录的文件名是这样的:

HG00119.mapped.ILLUMINA.bwa.GBR.low_coverage.20101123.bam.bai
HG00119.mapped.ILLUMINA.bwa.GBR.exome.20120522.bam_herc2_data.bam
HG00117.mapped.illumina.mosaik.GBR.exome.20110411.bam_herc2_phase1.bam
HG00117.mapped.illumina.mosaik.GBR.exome.20110411.bam.bai
NA20828.mapped.illumina.mosaik.TSI.exome.20110411.bam_herc2_phase1.bam
NA20828.mapped.ILLUMINA.bwa.TSI.low_coverage.20130415.bam_herc2_data.bam

我有一个包含在每行中的input.txt文件。

NA20828  
HG00119

如您所见,input.txt文件具有目录中文件名称的开头。

我想要做的是在input.txt中过滤目录中具有名称(在本例中只是开头)的文件。 我不知道自己是否清楚,但这是我迄今为止所做的代码。

use strict;
use warnings;

my @lines;                              
my @files = glob("*.mapped*");

open (my $input,'<','input.txt') or die $!;         
while (my $line = <$input>) {
    push (@lines, $line);               
}
close $input;

我使用glob来只过滤名称中映射的文件,因为我有其他文件,我不想查找。

我尝试了一些foreach循环,尝试了grep和regex,我很确定我的方法是正确的,我认为我的错误可能与范围有关。

我很感激任何帮助的人!谢谢!

2 个答案:

答案 0 :(得分:1)

好的,首先关闭 - 你的while循环是多余的。如果从列表上下文中的文件句柄读取,它会读取整个内容。

my @lines = <$input>; 

将与while循环相同。

现在,对于您的模式 - 您将一个列表与另一个列表匹配,但部分匹配。

chomp ( @lines );
foreach my $file ( @files ) {
    foreach my $line ( @lines ) {
        if ( $file =~ m/$line/ ) { print "$file matches $line"; }
    }
}

(是的,像grep或map这样的东西可以做到这一点,但我总觉得这两个让我头疼 - 它们更整洁,但是它们是隐式循环的,所以你并没有真正获得太多的算法效率)。

答案 1 :(得分:1)

您可以根据input.txt的内容构建正则表达式

my @lines = do {    
    open my $fh, '<', 'input.txt' or die $!;         
    <$fh>;
};
chomp @lines;
my $re = join '|', @lines;

然后使用

找到所需的文件
my @files = grep /^(?:$re)/, glob '*.mapped*';

请注意,如果input.txt中的列表包含任何正则表达式元字符,例如.*+等,则需要将其转义,可能使用quotemeta喜欢这个

my $re = join '|', map quotemeta, @lines;

并且最好还是这样做,除非你某些 永远不会成为文件中的此类字符。