【问题标题】:AWK - code not executing sequentially within the END ruleAWK - 代码未在 END 规则内按顺序执行
【发布时间】:2019-06-25 20:33:18
【问题描述】:

我正在处理一个文件,创建两个不同的关联数组来计算两种不同模式的频率(即字段 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

【问题讨论】:

  • 你想明确地close()每个管道。
  • @tripleee - GAWK user guide 表示 当打开文件或管道进行输出时,awk 会记住与其关联的文件名或命令,并随后写入同一文件或命令附加到先前的写入。文件或管道保持打开状态,直到 awk 退出。 如果我删除 | sort -n 命令或使用您的建议(即使用 close("sort -n")),则输出不会重叠。谢谢!

标签: awk


【解决方案1】:

如果您已经在使用 GNU Awk,您应该能够通过设置 PROCINFO["sorted_in"] 来避免使用子 shell 和外部实用程序。下面,我使用了@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 标志)。
【解决方案2】:

发生这种情况是因为您没有自己关闭打开的文件句柄。当脚本终止时,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)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-10
    • 2017-07-30
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    相关资源
    最近更新 更多