Python 在perl或bash中从colum解析

Python 在perl或bash中从colum解析,python,bash,perl,awk,Python,Bash,Perl,Awk,我正在处理的文件如下所示 NAMES n0 n1 n2 n3 n4 n5 n6 n7 REGION chr 1 100000 404 AAAAAAGA 992 TTTTTTTA 1146 CCCCGGCC 1727 CCCCCACC 1778 GCCCCCCC 需要根据列中的数字分割文件-为每1000个单位创建一个新文件,以便输出为e file1 NAMES n0 n1 n2 n3 n4 n5 n6 n7 REGION ch

我正在处理的文件如下所示

NAMES   n0  n1  n2  n3  n4  n5  n6  n7
REGION  chr 1   100000
404 AAAAAAGA
992 TTTTTTTA
1146    CCCCGGCC
1727    CCCCCACC
1778    GCCCCCCC
需要根据列中的数字分割文件-为每1000个单位创建一个新文件,以便输出为e

file1
 NAMES  n0  n1  n2  n3  n4  n5  n6  n7
    REGION  chr 404 992
    404 AAAAAAGA
    992 TTTTTTTA

file2
 NAMES  n0  n1  n2  n3  n4  n5  n6  n7
     REGION chr 1146    1778
1146 CCCCGGCC
1727 CCCCCACC
1778 GCCCCCCC
因此,每1000个单位拆分第一列(第一个是从1到1000)文件2是从1000到2000,并且每个文件中的开始和结束位置都会更改(以REG开头的行),因为第一个数字是文件第一行中的数字,另一个数字是hte文件最后一行中的数字。头文件必须存在于所有文件中。有没有办法用file1、file2等系统地命名这些文件/在所有文件中使用t来腾出空间

我试过了

awk '
NR==1 {
   h = $0
   k = 1000
   f = "file"k/1000
   print > f
   getline
   print "REGION chr",k-999,k > f
   next
} 
$1 <=k {
   print > f
   next
} 
{
   k=1000*int(1+$1/1000)
   f="file"k/1000
   print h > f
   print "REGION chr",k-999,k > f
   print > f
}' file
awk'
NR==1{
h=$0
k=1000
f=“文件”k/1000
打印>f
getline
打印“区域chr”,k-999,k>f
下一个
} 
1美元f
下一个
} 
{
k=1000*int(1+1美元/1000)
f=“文件”k/1000
打印h>f
打印“区域chr”,k-999,k>f
打印>f
}"档案"

您可以使用此awk命令:

awk 'function print_vals() {
   fn="file" c;
   print hdr > fn;
   print "REGION  chr", sn, en >> fn;
   for (i in a)
      print a[i] >> fn;
} NR == 1 {
   hdr=$0;
   c=0;
   next
} NF==2 && $1 >= 1000*c {
   if (c)
      print_vals();
   delete a;
   i=0;
   c++;
   sn=$1;
} NF==2 {
   a[++i]=$0;
   en=$1;
} END {
   print print_vals();
 }' file
验证:

cat file1
NAMES   n0  n1  n2  n3  n4  n5  n6  n7
REGION  chr 404 992
404 AAAAAAGA
992 TTTTTTTA

cat file2
NAMES   n0  n1  n2  n3  n4  n5  n6  n7
REGION  chr 1146 1778
1146    CCCCGGCC
1727    CCCCCACC
1778    GCCCCCCC

您有一个
awk
答案,但由于这个问题被标记为
perl
,我也将插入一个perl问题

#!/usr/bin/env perl
use strict;
use warnings;

my %seen;

my $header = <> . <>;
print $header;

my $last_sequence_number = 0;

open( my $output, ">", "output.$last_sequence_number.out" ) or die $!;
print {$output} $header;
$seen{$last_sequence_number}++;

while (<>) {
    my ($key) = split;
    next unless $key =~ m/^\d+$/;
    my $sequence_number = int( $key / 1000 );
    if ( not $sequence_number == $last_sequence_number ) {
        print "Opening new file for $sequence_number\n";
        close($output);
        open( $output, ">", "output.$sequence_number.out" ) or die $!;
        print {$output} $header unless $seen{$sequence_number}++;
        $last_sequence_number = $sequence_number;
    }
    print {$output} $_;
}
#/usr/bin/env perl
严格使用;
使用警告;
我看到的百分比;
我的$header=;
打印$header;
我的$last\u序列号=0;
打开(my$output,“>”,“output.$last\u sequence\u number.out”)或骰子$!;
打印{$output}$header;
$seen{$last_sequence_number}++;
而(){
我的($key)=拆分;
下一步除非$key=~m/^\d+$/;
我的$sequence_number=int($key/1000);
if(非$sequence\U number==$last\U sequence\U number){
打印“为$sequence\u编号打开新文件\n”;
关闭(产出美元);
打开($output,“>”,“output.$sequence_number.out”)或die$!;
打印{$output}$头,除非$seen{$sequence_number}++;
$last\u sequence\u number=$sequence\u number;
}
打印{$output}$\;
}
它的作用是:

  • 从输入中读两行,找出标题
  • 运行其余的输入,提取“数字位”
  • 将其除以1000,算出要写入的“文件号”
  • 如果相关,则为其打开一个新文件。(如果是第一次这样做,则写入一些标题)
  • 将当前行打印到当前打开的文件中

通过管道或
myscript.pl

调用此短Perl程序将处理命令行上指定为参数的文件。它会将任何不以数字开头的行推到
@header
上。否则,它会将这个数字除以1000,然后检查是否已经有一个文件为该千禧年打开。如果没有,它将打开一个文件进行输出,并将标题行打印到其中。然后将当前行打印到选定的文件句柄

use strict;
use warnings;
use 5.010;
use autodie;

my (@header, @fh);

while ( <> ) {

  if ( /^(\d+)/ ) {

    my $n = int $1 / 1000;

    unless ( $fh[$n] ) {
      my $file = sprintf 'file%d.txt', $n+1;
      open $fh[$n], '>', $file;
      print { $fh[$n] } @header;
    }

    print { $fh[$n] } $_;
  }
  else {
    push @header, $_;
  }
}

close $_ for grep $_, @fh;
输出-file2.txt
如果peopel能够判断q有什么问题,那就太好了。使用Perl脚本可以很容易地做到这一点。但是如果您先介绍一些Perl代码并说明您遇到的问题,那就更好了..嗯..恐怕我的Perl非常糟糕…所以我试着用awk来做…sorrI不认为这个问题过于宽泛。需求是明确定义的,并且OP在被提示后,显示了他的AWK代码,在NAMLIN的最后一行有一个TRAILIN T吗?因为这不太好……你在哪里找到一个尾随标签?@ KToui考虑接受这个答案,如果它对你有用的话,@anubhava这对测试集来说是可以的,但对这里的真实数据来说不是。你可以看看吗?有一些数字列不起作用,我无法用一个大文件进行测试。考虑制作一个小样本,这个解决方案不起作用。这样更容易调查和修改,如果需要的话。这是一件好事……您能告诉我如何提供多个输入文件,第一个文件的输出类似于文件1到10,下一个文件是文件11到20或24或更多?尽管请记住,“头”是列表中第一个文件的前两行。如果它们是一样的,那就没关系了。这是一件好事……你能告诉我如何提供多个输入文件,第一个文件的输出类似于文件1到10,下一个文件是文件11到20或24或更多吗?@ktoui:现在你正在更改要求!如果数字只是第一列除以1000,那么你就可以对每个文件运行这个程序,一次一个。答案是,不要像在euqestion中那样更改区域行中的数字。你能看一下吗
NAMES   n0  n1  n2  n3  n4  n5  n6  n7
REGION  chr 1   100000
404 AAAAAAGA
992 TTTTTTTA
NAMES   n0  n1  n2  n3  n4  n5  n6  n7
REGION  chr 1   100000
1146    CCCCGGCC
1727    CCCCCACC
1778    GCCCCCCC