Використовуючи awk для підсумовування значень стовпця, виходячи зі значень іншого стовпця


63

Я намагаюся підсумовувати певні числа у стовпці, використовуючи awk. Я хотів би підбити підсумок 3 колонки "ковалів", щоб отримати загальну кількість 212. Я можу підсумувати всю колонку, використовуючи, awkале не лише "ковалі". Я маю:

awk 'BEGIN {FS = "|"} ; {sum+=$3} END {print sum}' filename.txt

Також я використовую шпаклівку. Дякую за будь-яку допомогу.

smiths|Login|2
olivert|Login|10
denniss|Payroll|100
smiths|Time|200
smiths|Logout|10

Відповіді:


81
awk -F '|' '$1 ~ /smiths/ {sum += $3} END {print sum}' inputfilename
  • -FПрапор встановлює роздільник полів; Я розміщую це в одинарних лапках, тому що це особливий символ оболонки.
  • Потім $1 ~ /smiths/застосовується наступний {код блоку} лише до рядків, де перше поле відповідає регексу /smiths/.
  • Решта - те саме, що і ваш код.

Зауважте, що оскільки ви насправді не використовуєте регулярний вираз, а саме певне значення, ви можете так само легко використовувати:

awk -F '|' '$1 == "smiths" {sum += $3} END {print sum}' inputfilename

Що перевіряє рівність рядків. Це еквівалентно використанню регулярного вираження /^smiths$/, як згадується в іншій відповіді, яка включає в себе ^якор, який відповідає лише початку рядка (початок поля 1), і $якір повинен відповідати лише кінці рядка. Не знаєте, наскільки ви знайомі з регулярними виразами. Вони дуже потужні, але для цього ви можете так само легко використати перевірку рівності рядків.


3
До речі, моя улюблена посилання на awk - grymoire.com/Unix/Awk.html . Дуже корисна сторінка.
Wildcard

1
Дякую @Wildcard! Мені вдалося акуратно зібрати нестиснений розмір певних файлів у великому zip архіві на основі ваших порад :) unzip -lv /appl/tmp/data.lar | grep documentlibrary | awk '{sum += $1} END {print sum/1024/1024}'
Pawel

15

Інший підхід полягає у використанні awk асоціативних масивів, більше інформації тут . Цей рядок дає бажаний вихід:

awk -F '|' '{a[$1] += $3} END{print a["smiths"]}' filename.txt

Як побічний ефект, масив зберігає всі інші значення:

awk -F '|' '{a[$1] += $3} END{for (i in a) print i, a[i]}' filename.txt

Вихід:

smiths 212
denniss 100
olivert 10

Це правильна відповідь
PoVa

5

Дуже добре поки що. Все, що вам потрібно зробити, це додати селектор перед блоком, щоб додати суму. Тут ми перевіряємо, що перший аргумент містить лише "ковалі":

awk 'BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}'

Ви можете трохи скоротити це, вказавши роздільник поля як опцію. У awkце взагалі хороша ідея , щоб ініціалізувати змінні в командному рядку:

awk -F'|' '$1 ~ /^smiths$/ {sum+=$3} END {print sum}'

0
cat filename.txt | grep smiths | awk -F '|' '{sum+=$NF} END {print sum}'
  • -F можливість вказати роздільник.
  • $NF призначено для "останнього стовпця".

1
catі grepтут непотрібні.
Андрій

Чому греп не потрібен @Andrey? ОП хоче додати лише "ковалі" рядки. Вам потрібно буде змінити заяву awk, правда?
EL

1
@EL так, оператор awk слід змінити, /smiths/{...}якщо виклику grep немає. Це банальна модифікація, але вона дає значні переваги: ​​зменшує кількість запущених процесів, спрощує управління помилками та робить код яснішим.
Андрій

0

Я особисто хотів би зберегти awkрозділ якомога простіше і робити безліч можливостей без нього. Логіка, що склалася, не використовує силу трубопроводів Unix, і тому важче зрозуміти, налагодити чи змінити для тісно пов'язаних випадків використання.

cat filename.txt | perl -pe 's{.*|}{}g' | awk '{sum+=$1} END {print sum}'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.