1

我有一个用短字符串(@pos)填充的数组和第二个更大的数组(@exome)。我想在第二个数组中搜索与第一个数组匹配的字符串。目标是打印来自@exome 的所有匹配的行

我正在使用 perl,这是我目前所拥有的

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

my $pos = $ARGV[0];
my $exome = $ARGV[1];

open (F, "$pos") || die "Could not open $pos: $!\n";
my @pos = <F>;
close F;

open (F, "$exome") || die "Could not open $exome: $!\n";
my @exome = <F>;
close F;

foreach (@pos) {
    my @out = grep(/$_/, @exome);
    print @out
}
4

2 回答 2

2

问题:

  • /$_/意味着$_ =~ /$_/,所以也许你应该为模式使用不同的变量。
  • 您不会将文本转换为正则表达式模式(可以使用 来完成quotemeta
  • 您可以将同一行输出两次。
  • 请不要将全局变量用于文件句柄。
  • 无需将正在搜索的整个文件加载到内存中。

解决方案:

my ($pos_qfn, $exome_qfn) = @ARGV;

open(my $pos_fh, '<', $pos_qfn)
   or die("Could not open $pos_qfn: $!\n");
my @pos = <$pos_fh>;
chomp(@pos);

my $pat = join '|', map quotemeta, @pos;

open(my $exome_fh, '<', $exome_qfn)
   or die("Could not open $exome_qfn: $!\n");

while (<$exome_fh>) {
   print if /$pat/;
}
于 2013-04-05T17:32:18.117 回答
1

我认为@ikegami 给出了一个很好的答案,但是,他似乎在打印什么数组时出错了......也许@user2249959 想要打印@exome 数组......所需的核心代码不超过两行:

my $grep_pos = join '|', @pos;
my @matched_results = grep { /$grep_pos/ } @exome;

好吧,您可以在第二行立即打印出来,但数组中的元素之间不会有空格。两个 foreach 循环看起来不像 Perl,只是在我自己看来......

PS我加了三点注意
1.注意不可见的“\n”或“\r\n”
2.注意每个字符串开头和结尾的空格。
你可以用简单的代码解决以上两点,例如:

map { chomp; s/^\s*|\s*$// } @pos;

这将删除“\n”(如果有)和前面或末尾的空格(如果您认为没有意义)。在 grep
3 之前执行此操作。更重要的是!注意@pos 数组文件中的空行!
如果您的文件如下所示:

pos_1
pos_2
 <---- totally blank
pos_3

如果你仍然用'|'连接这些行,它将变成'pos_1|pos_2||pos_3',这意味着@exome中的任何东西都会匹配。(因为 ' || ')
chomp 或 s/// 不会有帮助,你必须自己跳这条线
小心点:)

于 2013-04-05T18:21:28.100 回答