Использование AWK для суммирования столбцов из разных файлов - PullRequest
0 голосов
/ 05 июля 2018

У меня есть куча данных, которые называются, скажем, от a0001.xyz до a0254.xyz. Я хочу суммировать 5-й столбец каждого файла и записать ответ в файл с именем output.txt. Поэтому я ищу файл с одним столбцом, содержащий суммы каждого файла .xyz.

Я пробовал что-то вроде этого:

awk -f sum.awk a0004.xyz > output.txt

, где sum.awk равно

#sum.awk
{ sum+=$5}
END { print sum }

он дает мне сумму 5-го столбца файла a0004.xyz и записывает ее в output.txt. Проблема в том, когда я меняю команду на:

awk -f sum.awk *.xyz > output.txt

снова он дает мне только одну из сумм среди всех файлов .xyz. Как я могу это исправить?

Надеюсь, мне удалось все ясно спросить

Ответы [ 5 ]

0 голосов
/ 05 июля 2018

Делать их все параллельно с GNU Parallel :

parallel -k -q awk '{s+=$5} END{print FILENAME,s+0}' ::: a*xyz

Пример вывода

a0001.xyz 20
a0002.xyz 40
a0254.xyz 55

Примечания:

  • -k означает «поддерживать вывод в порядке»
  • -q означает "процитируй мои вещи на awk, пожалуйста, потому что я ленивый"
  • s+0 означает обрабатывать s как число, поэтому, если оно не установлено, оно печатает 0

Или с gawk:

gawk '{s+=$5} ENDFILE{print FILENAME,s+0; s=0}' a*xyz

Пример вывода

a0001.xyz 20 
a0002.xyz 40
a0254.xyz 55
0 голосов
/ 05 июля 2018

Как то так?

$ tail a*.xyz
==> a0001.xyz <==
1 2 3 4 5 6 7
2 3 4 5 6 7 8

==> a0254.xyz <==
3 4 5 6 7 8 9
4 5 6 7 8 9 10
$ awk '{a[FILENAME]+=$5} END {for (i in a) printf "%4d %s\n", a[i], i}' a*.xyz
  11 a0001.xyz
  15 a0254.xyz

Скрипт awk здесь добавляет значение $5 к элементу массива с именем для текущего имени файла. После обработки всех вводимых данных, он проходит по массиву и печатает результаты с ключами, являющимися именами файлов, которые вносят вклад в каждое значение. Awk обрабатывает список имен файлов чисто и переносимо, без необходимости использования каналов.

0 голосов
/ 05 июля 2018
echo *.xyz | xargs -n 1 awk '{sum+=$5} END{print FILENAME,sum }' > output.txt

Вывод в output.txt (например,):

a0001.xyz 7
a0254.xyz 12
0 голосов
/ 05 июля 2018

Вы можете использовать bash для:

for file in *.mp3; do 
      awk -f sum.awk "$file"
done > output.txt
0 голосов
/ 05 июля 2018

Один из вариантов - сбросить результаты каждого файла в массив (проиндексированный по имени файла) и распечатать в конце:

awk '{a[FILENAME]+=$5} END{for(f in a) print f, a[f]}' *.xyz

При желании вы можете записать имя файла в переменную и печатать всякий раз, когда FNR == 1 и END:

awk 'FNR==1 && filename{print filename, sum; sum=0} {sum+=$1;filename=FILENAME} END{print filename, sum}' *.xyz
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...