Вычислить сумму столбца с помощью shellscript

У меня есть файл csv как text.csv , и я хочу рассчитать общую зарплату всех сотрудников. Данные в нем следующие:

Id,name,salary,designation
12,joe,thomas,253637,IT,admin
25,miacheal,364829,software engineer
46,mike,silva,adam, 374829479, senior, software, engineer
85,amber johnson,3728291,IT
24,Austin barclay, 3701830,software engineer

Я пробовал использовать

awk -F "," '{ SUM_SALARY += $3 } END { print SUM_SALARY }'

, но общая сумма неверна. Реальные данные насчитывают 5,5 миллионов записей.

0
22.03.2017, 07:31
2 ответа

Поля name содержат запятые, но не заключены в кавычки, поэтому awk будет видеть разные типы значений в 3 столбца на каждую строку.Это было бы так, даже если бы они были процитированы, но в показанном здесь случае даже настоящий анализатор CSV не поможет. Вот что я сделал, чтобы обойти это:

awk 'BEGIN { FS=",,*"; print 0 }
     (NR > 1) { gsub("[^0-9,]",""); printf "%d+\n", $2 }
     END { print "pq" }' < text.csv \
| dc

Сначала используется gsub для удаления всего, что не является цифрой или запятой в каждой строке, затем выводится значение нового второго столбца, где столбцы считается разделенным одной или несколькими запятыми. Блоки BEGIN и END заставляют данные работать с ожидаемым форматом dc .


Я использовал dc , потому что не знаю, действует ли awk как универсальный калькулятор произвольной точности. Если это так, вы можете вместо этого сделать:

awk -F ',,*' '(NR > 1){ gsub("[^0-9,]",""); SUM_SALARY += $2 } END { print SUM_SALARY }' < text.csv

Этот случай работает так же, как и предыдущий, за исключением того, что awk выполняет арифметические операции вместо dc . Здесь также используется переключатель -F , чтобы установить разделитель полей, чтобы избежать неиспользуемого в противном случае блока BEGIN .

1
28.01.2020, 02:33

Предполагая, что есть мигрирующее поле зарплаты (которое блуждает от поля 3 к 5 и обратно), два GNU grepа могут выделить зарплаты и передать их в numsum:

grep -o '[, ][[:digit:]]*,' test.csv | grep -o '[[:digit:]]*' | numsum 

Output:

382878066
1
28.01.2020, 02:33

Теги

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