Я обрабатываю один файл, создавая два разных ассоциативных массива для подсчета частоты двух разных шаблонов (т.е. полей 3 и 6, если они найдены).
Образец файла:
2019-06-20 : INFO : XYZ_6789 : [Command [cmd_zip_files]:] Standard output and error
2019-06-20 : INFO : ABC_1234 : License issue
Line with no timestamp
2019-06-20 : INFO : XYZ_6789 : [Command [cmd_zip_files]:] Standard output and error
2019-06-20 : INFO : ABC_1234 : License issue
Я хочу напечатать оба массива в конце, но их выходы перекрываются.
Я использую GNU Awk 4.1.3.
Я пытался использовать операторы «далее/продолжить», но они не кажутся ответом.
Возможно, я неправильно использую правило END.
#!/usr/bin/env awk
BEGIN {
FS = "\\)? : \\(?| \\| |[][]"
MSG_COL=3
CMD_COL=6
SEP = "================= = "
}
{
if (match ($MSG_COL, /^[A-Z]{3}_[0-9]+/))
msg_count[$MSG_COL]++
if ($MSG_COL == "XYZ_6789")
cmd_count[$CMD_COL]++
}
END {
print ">> Count of msg <<"
for (msg in msg_count)
if (msg_count[msg] > 0)
print msg_count[msg], msg | "sort -n"
print ">> Count of cmd <<"
for (cmd in cmd_count)
print cmd_count[cmd], cmd | "sort -n"
}
Я ожидаю, что мой код выдаст следующий результат:
>> Count of msg <<
2 ABC_1234
2 XYZ_6789
>> Count of cmd <<
2 cmd_zip_files
Хотя, я получаю это:
>> Count of msg <<
>> Count of cmd <<
2 ABC_1234
2 cmd_zip_files
2 XYZ_6789
@tripleee — Руководство пользователя GAWK указывает, что когда файл или канал открывается для вывода, awk запоминает имя файла или связанную с ним команду, и последующие записи в тот же файл или команду добавляются к предыдущим записям. Файл или канал остаются открытыми до выхода из awk. Если я либо удалю команду | sort -n
, либо воспользуюсь вашим советом (т. е. использую close("sort -n")
), вывод не будет перекрываться. Спасибо!
Если вы уже используете GNU Awk, вы сможете избежать подоболочек и внешних утилит, установив PROCINFO["sorted_in"]
. Ниже я использовал @val_num_desc
, который сортирует по убыванию числового значения (не по индексу):
awk -F ' : ' '
/^2019/ {Msg[$3]++; if (split($4, A, "[][]") > 1) Cmd[A[3]]++}
END {
PROCINFO["sorted_in"] = "@val_num_desc"
print ">> Count of msg <<"
for(m in Msg) print Msg[m], m
print ">> Count of cmd <<"
for(c in Cmd) print Cmd[c], c
}
' file
>> Count of msg <<
2 XYZ_6789
2 ABC_1234
>> Count of cmd <<
2 cmd_zip_files
Я не знал об этой расширенной функции GAWK. Спасибо, что нашли время, чтобы протестировать его и внести некоторые изменения в исходную реализацию. Хотя я не собираюсь использовать его, чтобы сделать код более переносимым, а также потому, что его значение является «глобальным» (т. е. оно влияет на весь обход массива для циклов). Я также хочу иметь возможность сортировать, используя разные поля (например, флаг сортировки -k).
Это происходит потому, что вы сами не закрываете открытые дескрипторы файлов. Awk закроет их для вас в конце концов, когда сценарий завершится, и в этот момент любой ожидающий буферизованный вывод будет сброшен, но порядок, в котором они закрываются, непредсказуем и ненадежен.
Измените блок END
на явно close
их в нужном вам порядке:
END {
print ">> Count of msg <<"
c = "sort -n"
for (msg in msg_count)
if (msg_count[msg] > 0)
print msg_count[msg], msg | c
close(c)
print ">> Count of cmd <<"
c = "sort -n"
for (cmd in cmd_count)
print cmd_count[cmd], cmd | c
close(c)
}
Вы хотите явно
close()
каждую трубу.