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我尝试手动打印正则表达式匹配后的后续行。

据我所知,我需要一个循环来遍历所有后续行,这就是我用 pattern 编写的variableStep chrom=chr1 span=25。但是后来,我意识到我需要一个退出机制,否则所有后续行都会被打印出来。

它是这样this exit pattern写的last if /^v.*$/,我需要弄清楚。因为我目前只打印first特定模式的实例。也没有我可以退出的空白行。如果我有一个空行,那么这段代码工作得很好(修改为last if /^$/)。我什至尝试使用非十进制字符作为/^\D.*$/,但它不起作用。What exit pattern should I use?

代码的其余部分是我的宝宝试图让程序工作,它只在模式匹配后打印单个后续行。

代码

#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. 如果我在第二个 if if if in a loop before and the flag has been set to "1"

    2. AND 行以数字开头。

  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

我喜欢,但更适合这种情况,请参阅:

$ 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 回答
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 回答