在不连续表中生成缺失值

时间:2014-04-12 20:35:09

标签: perl sed awk

文件包含多个表。每个表都有三个由制表符分隔的列。

第一列包含不连续的序列号。我想打印缺少的序列号,第二和第三列为0 0。

输入文件

Pos freq catagory
    13    1       4
    14    2       3
    17    5       2
    20    3       2 <<<<<
    21    1       4
    25    1       4
Pos freq catagory
    10    1       4
    12    2       3
    13    5       2
    14    3       2 <<<<<
    15    1       4

输出文件

Pos freq catagory
    13    1       4
    14    2       3
    15    0       0
    16    0       0
    17    5       2
    18    0       0
    19    0       0
    20    3       2 <<<<<
    21    1       4
    22    0       0
    23    0       0
    24    0       0
    25    1       4
Pos freq catagory
    10    1       4
    11 0 0 
    12    2       3
    13    5       2
    14    3       2 <<<<<
    15 1 4

请你帮我用Perl,sed或awk做这件事吗?

3 个答案:

答案 0 :(得分:1)

以防您对coreutils + sed解决方案感兴趣:

$ join -a2 -j1 -t $'\t' input_file <(seq 13 25) | sed 's/^[^[:space:]]*$/&\t0\t0/'
13      1       4
14      2       3
15      0       0
16      0       0
17      5       2
18      0       0
19      0       0
20      3       2
21      1       4
22      0       0
23      0       0
24      0       0
25      1       4

答案 1 :(得分:1)

$ awk -F'\t' -v OFS="\t" '!p{p=$1-1}++p<$1{for(p;p<$1;p++)print p,0,0}7' file 
13  1   4
14  2   3
15  0   0
16  0   0
17  5   2
18  0   0
19  0   0
20  3   2
21  1   4
22  0   0
23  0   0
24  0   0
25  1   4

答案 2 :(得分:1)

这个Perl程序不必要地长,因为它试图在填充的数据行中使用原始文件中的间距。如果第一个字段是带有前导空格的固定长度,那么它也会出错。

是的,我知道编写猜测正确规范的软件是愚蠢的。

use strict;
use warnings;

my $seq;

while (<>) {
  if ( / ( (\s*) (\d+) ) /x ) {
    if (defined $seq) {
      printf "%s%d\t0\t0\n", $2, $_ for $seq+1 .. $3-1;
    }
    $seq = $3;
  }
  else {
    $seq = undef;
  }
  print;
}

<强>输出

Pos freq catagory
    13    1       4
    14    2       3
    15  0 0
    16  0 0
    17    5       2
    18  0 0
    19  0 0
    20    3       2 <<<<<
    21    1       4
    22  0 0
    23  0 0
    24  0 0
    25    1       4
Pos freq catagory
    10    1       4
    11  0 0
    12    2       3
    13    5       2
    14    3       2 <<<<<
    15    1       4