find
и cpio
были созданы Диком Хейтом, а не людьми, написавшими большинство исходных утилит Unix. В то время не существовало библиотеки синтаксического анализа аргументов командной строки, которую можно было бы связать как библиотеку, и которая обеспечила бы / стимулировала некоторую согласованность (в середине 80-х у меня был исходный код для getopt
в нескольких системах)
Когда люди используют команды и их аргументы в сценариях, становится трудно изменить синтаксис существующей функциональности.
Сценарий 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
. Однако в ближайшее время вы этого не сделаете. См. здесь , чтобы понять, почему.
Альтернативное решение с 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
, если он не пустой, и присвойте массиву поля новой строки @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