У меня есть файл 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 миллионов записей.
Поля 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
.