因此,我有一个目录,其中的文件名如下:
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,我很确定我的方法是正确的,我认为我的错误可能是关于范围的。
我会感谢任何帮助的人!谢谢!
发布于 2015-03-02 13:34:03
好的,首先-您的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之类的东西可以做到这一点,但我总是发现这两个让我头疼--它们更整洁,但它们在隐式循环,所以算法效率不高)。
发布于 2015-03-02 15:21:41
您可以从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
中的列表包含任何regex元字符,如.
、*
、+
等,则需要转义它们,可能需要使用如下所示的quotemeta
my $re = join '|', map quotemeta, @lines;
而且,除非您确信文件中永远不会有这样的字符,否则最好还是这样做。
https://stackoverflow.com/questions/28818912
复制相似问题