我有一个如下所示的文件:
文件
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
需要什么
我需要做的是,对于所有说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?
代码的剩余部分是我的宝贝尝试让程序运行,它只在模式匹配后打印单个后续行。
代码
#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;
感谢您抽出宝贵时间来回答我的问题。我会很感激任何提示和建议。
答案 0 :(得分:2)
好的,我很想念n
部分,每场比赛都有所不同,经过测试和运作:
my $found = 0;
while (<$fh>) {
if ( $found && /^\d/ ) {
print $_;
}
else {
$found = 0;
}
if (/^variableStep chrom=chr2 span=25/) {
$found = 1;
}
}
这样它会打印以数字开头的所有后续行。
<强>解释强>
这里的问题是,每次调用<$fh>
时它都会读取下一行,所以如果你测试行内容而你的测试失败了,你就不应该进行下一个循环,因为那样下一行被读取,你丢失了测试失败的行。
所以我来到这个解决方案:
我使用标志知道我在哪种模式下,是否要搜索要打印的行?
仅输入第一个if
如果我在第二个中,如果在之前的循环中并且标志已设置为“1”
并且该行以数字开头。
当此测试失败时,即开头没有带数字的行时,我重置了标志,如果它以“variableStep ...”开头,则有机会再次查看同一行。 / p>
答案 1 :(得分:1)
下面的Oneliner应该这样做(假设输出文件尚不存在):
perl -lne '/variableStep/ && open($fh, ">>", $_) && next; print $fh $_;' input.txt
-
btw:||
运算符具有高优先级(man perlop
),因此命令:
open OUT1, ">Trial_chr1.out" || die $!;
被perl理解为
open OUT1, (">Trial_chr1.out" || die $!);
要进行错误检查,您应该使用and
运算符,或使用括号来强制执行所需的行为
答案 2 :(得分:0)
$ awk '
{if ($0 ~ /^variableStep/) {file="output_file_"++c"_"$1"_"$2"_"$3}
else{print $0 > file}}
' file.txt
$ ls -l output_file_*
答案 3 :(得分:0)
使用perl和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_*