Я решил не читать файл дважды, а просто сохранить выходные данные в массиве перед печатью. Вот как это сделать:
Шаг 1: исправьте синтаксическую ошибку, которую вы получите от некоторых awk, когда они предполагают, что sum
является скаляром из-за того, что вы вызвали length(sum)
до того, как он был использован в качестве массива, добавив операцию массива delete sum
в раздел BEGIN (вы можете просто удалить тест на длину (сумму), поскольку он не делает ничего полезного в вашем коде, но я хотел объяснить проблему и как ее решить в целом).
BEGIN { FS=": *"; delete sum }
Шаг 2: измените функцию format()
, чтобы загружать массив значений для последующего вывода вместо немедленного вывода этих значений:
function format() {
if ( length(sum) > 0 ) {
for (dept in sum) {
vals[++numVals] = sprintf("%-9s%-12s%10.2f", substr(user,1,9), substr(dept,1,12), sum[dept])
}
delete sum
amount = 0
}
}
Шаг 3: добавьте цикл в разделе КОНЕЦ, чтобы на самом деле печатать:
END {
format()
for (valNr=1; valNr<=numVals; valNr++) {
print vals[valNr]
}
}
На этом этапе вы получите тот же результат, что и ваш существующий скрипт, но он настроит нас на добавление новых необходимых вам функций:
Шаг 4: сохранить каждую комбинацию пользователь + отдел как индексы массива usrdpt[]
:
/Amount/ {
dept = f["departmentId"]
total = f["Total"]
sum[dept] += $2
usrdpt[user,dept]
amount += $2
}
Шаг 5: напечатайте количество уникальных индексов нового массива usrdpt[]
в разделе END перед печатью предыдущих значений:
END {
format()
print length(usrdpt)
for (valNr=1; valNr<=numVals; valNr++) {
print vals[valNr]
}
}
Результат:
$ cat tst.awk
BEGIN { FS=": *"; delete sum }
{
gsub(/^ +| +$/,"")
f[$1] = $2
}
/Amount/ {
dept = f["departmentId"]
total = f["Total"]
sum[dept] += $2
usrdpt[user,dept]
amount += $2
}
$1 == "User" {
if (NR>1) {
format()
}
user = $2
}
END {
format()
print length(usrdpt)
for (valNr=1; valNr<=numVals; valNr++) {
print vals[valNr]
}
}
function format() {
if ( length(sum) > 0 ) {
for (dept in sum) {
vals[++numVals] = sprintf("%-9s%-12s%10.2f", substr(user,1,9), substr(dept,1,12), sum[dept])
}
delete sum
amount = 0
}
}
.
$ awk -f tst.awk file
7
user1 dept1 55.00
user1 dept2 25.00
user2 dept1 2.40
user2 dept2 2.40
user2 dept3 2.40
user3 dept2 0.20
user4 dept3 2.00
Полагаю, вы сможете выяснить, как сохранить, а затем распечатать значение Total
.