Сумма столбцов для строк, содержащих определенный термин

find и cpio были созданы Диком Хейтом, а не людьми, написавшими большинство исходных утилит Unix. В то время не существовало библиотеки синтаксического анализа аргументов командной строки, которую можно было бы связать как библиотеку, и которая обеспечила бы / стимулировала некоторую согласованность (в середине 80-х у меня был исходный код для getopt в нескольких системах)

Когда люди используют команды и их аргументы в сценариях, становится трудно изменить синтаксис существующей функциональности.

2
11.07.2016, 11:33
2 ответа

Сценарий awk , который не хранит ни входной файл, ни всю таблицу результатов в памяти:

FNR == 1   { for(i = 1; i <= NF; i++) a[i] = $i;  next }
$1 == a[1] { for(i = 2; i <= NF; i++) a[i] += $i; next }
{
    printf "%s", a[1]; a[1] = $1;
    for(i = 2; i <= NF; i++) { printf "\t%s", a[i]; a[i] = $i };
    printf "\n";
}
END {
    printf "%s", a[1];
    for(i = 2; i <= NF; i++) printf "\t%s", a[i];
    printf "\n";
}

Чтобы запустить его:

awk -f script.awk data.txt

Результаты:

ABCD:1234       1.23    1.33    1.04    0
EFGH:5678       0       1.90    0.12    8.21
IJKL:9999       3.98    0       38.9    11.64

Кстати, это можно сделать с помощью sed . Однако в ближайшее время вы этого не сделаете. См. здесь , чтобы понять, почему.

4
29.04.2021, 00:12

Альтернативное решение с perl

$ perl -nale '
if(!$seen{$F[0]}++)
{
    print join "\t", @a if @a;
    @a = @F[0..$#F];
}
else
{
    $a[$_] += $F[$_] foreach(1..$#F);
}
print join "\t", @a if eof;
' data.txt 
ABCD:1234   1.23    1.33    1.04    0
EFGH:5678   0       1.90    0.12    8.21
IJKL:9999   3.98    0       38.9    11.64
  • -a разбивает входную строку на пробелы и сохраняет их в массиве @F
  • первое поле строки используется как ключ к хеш-переменной % seen , если ключ не найден, распечатайте содержимое массива @a , если он не пустой, и присвойте массиву поля новой строки
  • Если ключ уже существует, увеличьте содержимое массива (от 2-го поля до конца) с соответствующим содержимым из текущей строки
  • Для обработки последней записи распечатайте содержимое массива @a снова при достижении конца файла


Для повторяющегося вопроса: Добавьте все столбцы отдельно в linux, если в первом столбце есть такие же записи

$ perl -nale '
if(!$seen{$F[0]}++)
{
    print join "\t", @a if @a;
    @a = @F[0..$#F];
}
else
{
    $a[$_] += $F[$_] foreach(1..$#F);
}
print join "\t", @a if eof;
' filename.txt 
AC1481523   6   6   6   6
AC1481676   6   5   6   8


Решение с построением хеша массивов и выводом хеша в конце:

$ perl -nale '
if($h{$F[0]})
{
    $h{$F[0]}[$_] += $F[$_] foreach (1..$#F)
}
else
{
    $h{$F[0]} = [@F]
}
END { print join "\t",@{$h{$_}} foreach sort keys %h }
' data.txt
ABCD:1234   1.23    1.33    1.04    0
EFGH:5678   0       1.90    0.12    8.21
IJKL:9999   3.98    0       38.9    11.64
0
29.04.2021, 00:12

Теги

Похожие вопросы