私は、次の形式の生物学的配列データ (FASTA) を頻繁に使用しています。先頭の左山かっこは、新しい配列ヘッダーを示す区切り文字として使用されます。これらのファイルには、多くの場合、テキストの折り返しがあります (ヘッダーを除く)。
>header1
ACTGACTGACTGACTG
ACTGACTGACTGACTG
>header2
CTGGGACTAGGGGGAG
CTGGGACTAGGGGGAG
ファイル全体が数 MB (場合によっては GB) になる可能性があるため、ファイル全体をメモリに読み込むことを避けたいことがよくあります。そのため、while ループと 1 行ずつの読み込みに集中するようにしています。ただし、ファイルの先頭または末尾に独自の処理を行うためにコードを追加する必要があることがよくあります。たとえば、今日、一部のファイルのテキスト ラッピングを削除したいと考えました。
while (my $line = <$inputfasta_fh>) {
chomp($line);
if ($line =~ /^>/) {
print $outputfasta_fh "$line\n";
}
else {
print $outputfasta_fh $line;
}
}
しかし、最初のヘッダーを除くすべてのヘッダーの前に改行が必要であることに気付きました (そうしないと、前のシーケンスの最後に連結されます)。だから、これは私の大雑把な回避策です。
my $switch = 0;
while (my $line = <$inputfasta_fh>) {
chomp($line);
if ($line =~ /^>/) {
if ($switch == 1) {
print $outputfasta_fh "\n";
}
print $outputfasta_fh "$line\n";
$switch = 1;
}
else {
print $outputfasta_fh $line;
}
}
以前は、最後の行で何かをする必要があるという他の問題がありました。たとえば、fasta を読み取り、各ヘッダーを保存し、そのシーケンスの長さを (再び行ごとに) カウントし、指定した範囲内にある場合は、別のファイルに保存するスクリプトがありました。長さが最大を超えるとカウントは中止されますが、別のヘッダーまたはファイルの終わりに到達するまで、長さが最小を超えているかどうかはわかりません。後者の場合、while ループの下で長さチェック サブルーチンを繰り返さなければなりませんでした。最後の部分を繰り返すことは避けたいと思います。
my $length = 0;
my $header;
my @line_array;
while (my $line = <$inputfasta_fh>) {
chomp($line);
if ($line =~ /^>/) {
# check if previous sequence had a length within range
if (check_length($length, $minlength, $maxlength) == 1) {
print $outputfasta_fh "$header\n";
print $outputfasta_fh join ("\n", @line_array), "\n";
}
undef @line_array;
$header = $line;
$length = 0;
}
else {
if ($length <= $maxlength) { # no point in measuring any more
push (@linearray, $line);
$length += length($line);
}
}
}
#and now for the last sequence
if (check_length($length, $minlength, $maxlength) == 1) {
print $outputfasta_fh "$header\n";
print $outputfasta_fh join ("\n", @line_array), "\n";
}
sub check_length {
my ($length, $minlength, $maxlength) = @_;
if (($length >= $minlength) && ($length <= $maxlength)) {
return 1;
}
else {
return 0;
}
}
それで、私の基本的な質問は、カウンターに頼ったり、ループの外でコードを繰り返したりせずに、ループ内で何かをしたいことをどのように示すかということです。助けてくれてありがとう!