awk вычитать разные столбцы - PullRequest
0 голосов
/ 12 ноября 2018

Я хочу сгруппировать дублирующиеся строки и вычесть значения в столбцах из этих строк.Любая идея, как я могу это сделать?

Пример:
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 в a) {s = j;для (i = 2; i <= NF; i ++) {s = s "" a [j] [i]};print s}} '</p> Но изменение + = на - = не вычитает, оно все равно делает сумму значений, но ставит знак минус.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018
$ 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
0 голосов
/ 12 ноября 2018

Если это не обязательно должен быть 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}}";
}

Он производит вывод в отсортированном порядке, как в вашем примере. Если предполагается, что строки располагаются в том порядке, в котором они впервые появляются в вашем реальном вводе, это тоже выполнимо. Это не было ясно из вашего образца, так как он уже отсортирован.

Также не требуется, чтобы дубликаты были последовательными - это важно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...