2

次のようなファイルがあります。

ファイル

variableStep chrom=chr1 span=25
10076   0.84
10101   1
10126   1
10151   1
10176   1
10201   1
10226   1.72
variableStep chrom=chr1 span=25
10251   2
10276   1.16
10301   1
10326   1
10351   1
10376   1
10401   1
10426   0.28
11451   0.04
variableStep chrom=chr2 span=25
9781451     2
19781476    2
19781501    2
19781526    2
19781551    1
19781576    1
19781601    0.48
variableStep chrom=chr2 span=25
19781826    0.28
19781851    1
19781876    1
19781901    1
19781926    1
19781951    1.48
19781976    3.68
19782001    4.56
19782026    4
variableStep chrom=chr3 span=25
4813476 1
24813501    1
24813526    1
24813551    1
24813576    1.88
24813601    2
variableStep chrom=chr3 span=25
24813626    1.4
24813651    1.48
24813676    2
24813701    2
24813726    2
24813751    2
variableStep chrom=chr4 span=25
24815401    2.24
24815426    3
24815451    3
24815476    3
24815501    3
24815526    2.04
variableStep chrom=chr4 span=25
24815551    2
24815576    1.76
24815601    0.76
24815951    0.48
24815976    1
24816001    1
24816026    1
24816051    1
variableStep chrom=chr5 span=25
24817226    0.92
24817251    1.48
24817276    3
24817301    3
variableStep chrom=chr5 span=25
24817326    3
24817351    3
24817376    3
24817401    3.04
24817426    3.08

必要なもの

私がする必要があるのは、 say のすべてのインスタンスについてvariableStep chrom=chr1 span=25、後続のn行を出力ファイルに出力することです。n私が言及しなければならないのは、非常に変化しやすいことです。実際のファイルでは、300,000 から 500,000+ の範囲で変動する可能性があります。

望ましい出力

1.Output_file_1_for_variableStep chrom=chr1 span=25

10076   0.84
10101   1
10126   1
10151   1
10176   1
10201   1
10226   1.72
10251   2
10276   1.16
10301   1
10326   1
10351   1
10376   1
10401   1
10426   0.28
11451   0.04

2._Output_file_2_for_variableStep chrom=chr2 span=25

9781451     2
19781476    2
19781501    2
19781526    2
19781551    1
19781576    1
19781601    0.48
19781826    0.28
19781851    1
19781876    1
19781901    1
19781926    1
19781951    1.48
19781976    3.68
19782001    4.56
19782026    4

3._Output_file_3_for_variableStep chrom=chr3 span=25

4813476     1
24813501    1
24813526    1
24813551    1
24813576    1.88
24813601    2
24813626    1.4
24813651    1.48
24813676    2
24813701    2
24813726    2
24813751    2

4._Output_file_4_for_variableStep chrom=chr4 span=25

24815401    2.24
24815426    3
24815451    3
24815476    3
24815501    3
24815526    2.04
24815551    2
24815576    1.76
24815601    0.76
24815951    0.48
24815976    1
24816001    1
24816026    1
24816051    1

5._Output_file_5_for_variableStep chrom=chr5 span=25

24817226    0.92
24817251    1.48
24817276    3
24817301    3
24817326    3
24817351    3
24817376    3
24817401    3.04
24817426    3.08

背景
私はまだ自分自身を Perl の初心者だと思っているので、私が書いたコードはタスクを完全には達成していません。

実際、次のコードは、私がそれを機能させようとしていた 3 つの方法を示しています。パターン付きのコードについてはvariableStep chrom=chr1 span=25、正規表現が手動で一致した後、後続の行を印刷しようとしました。

私が考え出したことから、後続のすべての行を実行するにはループが必要です。これは、パターンで記述したものvariableStep chrom=chr1 span=25です。しかし、その後、終了メカニズムが必要であることに気付きました。そうしないと、後続のすべての行が印刷されてしまうからです。

それは私が理解する必要があるとthis exit pattern書かれてlast if /^v.*$/います。first私が持っているものは現在、特定のパターンのインスタンスのみを印刷しているためです。終了できる空白行もありません。空白行があったとしても、このコードは完全に正常に機能しています ( に変更last if /^$/)。として非小数点文字を使用しようとしました/^\D.*$/が、機能しません。What exit pattern should I use?

コードの残りの部分は、プログラムを機能させるための私の赤ん坊の試みであり、パターン一致の後に続く 1 行のみを出力します。

コード

#Trial code to parse main file
use 5.014;
use warnings;

#Assign filename
my $file = 'trial.txt';

#Open filename
open my $fh, '<' , $file || die $!;

#Open output
open OUT1, ">Trial_chr1.out" || die $!;
open OUT2, ">Trial_chr2.out" || die $!;
open OUT3, ">Trial_chr3.out" || die $!;
open OUT4, ">Trial_chr4.out" || die $!;
open out5, ">Trial_chr5.out" || die $!;

#Read in file
while(<$fh>){
    chomp;
    if (/^variableStep chrom=chr1 span=25/){

        my $nextline1 = <$fh>;#means next line after pattern match
        my $nextline2 = <$fh>;
        my $nextline3 = <$fh>;
        my $nextline4 = <$fh>;
        my $nextline5 = <$fh>;
        my $nextline6 = <$fh>;
        my $nextline7 = <$fh>;
        print OUT1 $nextline1;
        print OUT1 $nextline2;
        print OUT1 $nextline3;
        print OUT1 $nextline4;
        print OUT1 $nextline5;
        print OUT1 $nextline6;
        print OUT1 $nextline7;

    }elsif(/^variableStep chrom=chr2 span=25/){

        my @grabbed_lines; #Initialize array to store lines after pattern match
        while (<$fh>){ #Read subsequent lines while in a loop

        last if /^v.*$/; #Break out of the loop if line encountered begins with v
        push @grabbed_lines, $_;# As long as the above condition is false, push the lines into the array

        }print OUT2 @grabbed_lines; # Print the grabbed lines

    }elsif(/^variableStep chrom=chr3 span=25/){
        my $nextline = <$fh>;
        print OUT3 $nextline;

    }elsif(/^variableStep chrom=chr4 span=25/){
        my $nextline = <$fh>;
        print OUT4 $nextline;
    }elsif(/^variableStep chrom=chr5 span=25/){
        my $nextline = <$fh>;
        print out5 $nextline;
    }
}


#Exit
exit;

私の質問に時間を割いていただきありがとうございます。ヒントや提案をいただければ幸いです。

4

4 に答える 4

2

わかりました、私はそのn部分を誤解しました、それは試合ごとに異なります、これはテストされて機能しています:

my $found = 0;

while (<$fh>) {
    if ( $found && /^\d/ ) {
        print $_;
    }
    else {
        $found = 0;
    }

    if (/^variableStep chrom=chr2 span=25/) {
        $found = 1;
    }
}

このようにして、数字で始まる後続のすべての行を出力します。

説明:

ここでの問題は、呼び出すたび<$fh>に次の行が読み取られることです。したがって、行の内容をテストしてテストが失敗した場合は、次のループを実行しないでください。次の行が読み取られ、次の行が失われるためです。テストは失敗しました。

だから私はこの解決策に到達しました:

  1. フラグを使用して、自分がどのモードにあるかを確認します。印刷する行を検索していますか?

  2. 最初のif入力のみ

    1. 私が2番目にいた場合、前にループに入っていて、フラグが「1」に設定されている場合

    2. そして、行は数字で始まります。

  3. このテストが失敗した場合、つまり先頭に数字が含まれる行がない場合、フラグをリセットし、「variableStep ...」で始まる場合は、同じ行をもう一度確認する機会があります。

于 2013-02-28T07:29:59.907 に答える
1

以下のOnelinerがトリックを実行する必要があります(出力ファイルがまだ存在しないと仮定します):

perl -lne '/variableStep/ && open($fh, ">>", $_) && next; print $fh $_;' input.txt

-

ところで:||演算子は優先度が高い(man perlop)ので、コマンド:

open OUT1, ">Trial_chr1.out" || die $!;

perlによって次のように理解されます

open OUT1, (">Trial_chr1.out" || die $!);

エラーチェックを行うには、and代わりに演算子を使用するか、かっこを使用して目的の動作を強制する必要があります

于 2013-02-28T11:08:10.027 に答える
0

File::Slurp便利なモジュールの使用:

use strict; use warnings;
use File::Slurp;

my ($c, $file);

while (<>) {
    if (/^variableStep\s+chrom=\w+\s+span=\d+/) {
        $c++;
        $file = $&;
        $file =~ s/\s/_/g;
        $file = "output_file_${c}_" . $file;
    }
    else {
        append_file $file, $_;
    }
}

使用法 :

$ perl ./script.pl file.txt
$ ls -l output_file_*
于 2013-02-28T08:05:13.270 に答える
0

が大好きですが、この場合はの方が適しています。次を参照してください。

$ awk '
    {if ($0 ~ /^variableStep/) {file="output_file_"++c"_"$1"_"$2"_"$3}
    else{print $0 > file}}
' file.txt

$ ls -l output_file_*
于 2013-02-28T07:47:02.083 に答える