每 10000 个数字(不是行)拆分文件

aga*_*sia 8 awk text-processing split

我有一个如下所示的文件:

chr19   61336212        +       0       0       CG      CGT    
chr19   61336213        -       0       0       CG      CGG    
chr19   61336218        +       0       0       CG      CGG    
chr19   61336219        -       0       0       CG      CGC    
chr19   61336268        +       0       0       CG      CGG    
chr19   61336269        -       0       0       CG      CGA    
chr19   61336402        +       0       0       CG      CGG    
chr19   61336403        -       0       0       CG      CGT    
Run Code Online (Sandbox Code Playgroud)

我想为第二个字段的每 10000 个间隔(不是行,而是数字间隔)拆分此文件。因此,对于此文件,我想从第一行(带有 61336212 的行)拆分为具有或最多为 61346211(61336212+9999)的行,然后从 61346212 拆分为 61356211,依此类推。如您所见,第二个字段/列中的数字未“填充”。

有没有办法做到这一点?

Sté*_*las 13

awk 'NR==1 {n=$2}
     {
       file = sprintf("file.%.4d", ($2-n)/10000)
       if (file != last_file) {
         close(last_file)
         last_file = file
       }
       print > file
     }'
Run Code Online (Sandbox Code Playgroud)

会写file.0000file.0001...(数量是int(($2-n)/10000)其中n$2第一个行)。

请注意,一旦我们停止写入文件,我们就会关闭文件,否则,您将在几百个文件后达到同时打开文件的数量限制(GNUawk可以解决该限制,但性能会迅速下降)。

我们假设这些数字总是在上升。

  • 你能解释一下发生了什么吗? (3认同)

ste*_*eve 7

破解单行版。不过,也许比这个论坛更适合Code Golf。这将生成 split1、split2、split3 等作为文件名。

awk '{if($2>b+9999){a++;b=$2}print >"split" a}' file.txt
Run Code Online (Sandbox Code Playgroud)

要具有名为 split001、split002、split003 的输出文件,需要额外的sprintf

awk '{if($2>b+9999){a++;b=$2}print >sprintf("split%03d",a)}' file.txt
Run Code Online (Sandbox Code Playgroud)

为避免@Stéphane Chazelas 发现的 gawk 减速问题,请使用 perl:

perl -ne '(undef,$a)=split(/\s+/,$_);if($a>$b+9999){$c++;$b=$a}open(D,sprintf(">>ysplit%03d",$c));print D' <file.txt
Run Code Online (Sandbox Code Playgroud)