1

短い文字列 (@pos) で満たされた 1 つの配列と、2 つ目の大きな配列 (@exome) があります。最初の文字列と一致するものを 2 番目の配列で検索したいと考えています。目標は、一致する @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) 。
  • 同じ行を 2 回出力することは可能です。
  • ファイル ハンドルにグローバル変数を使用しないでください。
  • 検索対象のファイル全体をメモリにロードする必要はありません。

解決:

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 配列を印刷したいのかもしれません... 必要なコアコードは 2 行以内です:

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

2 行目ですぐに出力できますが、配列の要素間に空白はありません。私の意見では、2 つの foreach ループは Perl のようには見えません...

PS 注意点を 3 点追加しました
。 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 に答える