awk减去不同的列

时间:2018-11-12 13:13:40

标签: linux awk

我想对重复的行进行分组,并从这些行中减去cols中的值。知道我该怎么做吗?

示例:

dbstat 100 90 80 60 1000 
dbstat 10 10 10 20 
test 5 5
output should be: 
dbstat 90 80 70 40 1000 
test 5 5

更新: 对于其他文件,我必须对匹配行的值求和,使用以下命令可以正常工作:

awk'{for(i = 2; i <= NF; i ++){a [$ 1] [i] + = $ i}} END {for(j in a){s = j;对于(i = 2; i <= NF; i ++){s = s“” a [j] [i]};打印s}}''

但是将+ =更改为-=不会减去,它仍然是值的总和,但在前面加上减号。

谢谢。

2 个答案:

答案 0 :(得分:1)

$ cat file
test1 100 20 25 30
test1 10 10
test1 30 0 2
test2 500
test2 100 50 90
test2 10 0
test3 100 100 100
$
$ cat tst.awk
p != $1 {
    for (i in c)
        p = p OFS c[i]
    if (p)
        print p
    p = $1
    delete c
    for (i = 2; i <= NF; ++i)
        c[i] = $i
    next
}
{
    for (i = 2; i <= NF; ++i)
        c[i] -= $i
}
END {
    for (i in c)
        p = p OFS c[i]
    print p
}
$
$ awk -f tst.awk file
test1 60 10 23 30
test2 390 -50 -90
test3 100 100 100

如果未对重复的列进行分组:

$ cat file2
test2 500
test1 100 20 25 30
test2 100 50 90
test1 30 0 2
test2 10 0
test3 100 100 100
test1 10 10
$
$ cat tst2.awk
{
    f = ($1 in a)
    for (i = 2; i <= NF; ++i)
        a[$1][i] -= (f ? $i : -$i)
}
END {
    for (k in a) {
        o = k
        for (i in a[k])
            o = o OFS a[k][i]
        print o
    }
}
$
$ awk -f tst2.awk file2
test1 60 10 23 30
test2 390 -50 -90
test3 100 100 100

答案 1 :(得分:0)

如果不必awk,此perl脚本将为您的示例输入提供所需的输出:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use List::MoreUtils qw/pairwise/; # Non-core; install through your OS or CPAN.

my %records;

while (<>) {
  my ($key, @cols) = split /\s+/;
  $records{$key} =
    [ pairwise { defined $a ? $a - ($b // 0) : $b } @{$records{$key}}, @cols ];
}

foreach my $key (sort keys %records) {
  say "$key @{$records{$key}}";
}

它会像您的示例一样按排序顺序生成输出。如果行应该按照它们第一次出现在实际输入中的顺序排列,那也是可行的。您的样本尚不清楚,因为该样本开始排序。

它也不要求重复是连续的-重要吗?