试图在 jq 中重现 awk

Trying to reproduce awk in jq

前言:企业网络Engineer/Architect(非程序员)。
概要:日志从 txt 输出移动到 json
问题:未成功尝试从正常运行的 awk 数据提取迁移到使用 jq 反对 json 使用单行。
活跃的 awk:

awk '
   BEGIN{ FS="\t" }
  { arr[ FS ] += ; count[ FS ] += 1 }
  END{ for (key in arr) printf "%s%s%s%s%s\n", key, FS, count[key], FS, arr[key] }
' | sort -nrk 4 | head -1 | awk '{ print " | "" | "/60/60 }'

最终结果:使用 jq 计算 src/dst ip 地址和 dst 端口的重复条目,并添加连接的累计持续时间。

样本JSON输入

{
  "ts": 1636xxxxx.41xxx34,
  "uid": "hex_code",
  "id.orig_h": "10.x.x.11",
  "id.orig_p": 42996,
  "id.resp_h": "10.x.x.123",
  "id.resp_p": 53,
  "proto": "udp",
  "service": "dns",
  "duration": 0.01117664844,
  "conn_state": "SF",
  "local_orig": true,
  "local_resp": true,
  "missed_bytes": 0,
  "history": "Dd",
  "orig_pkts": 1,
  "orig_ip_bytes": 71,
  "resp_pkts": 1,
  "resp_ip_bytes": 71
}
{
  "ts": 1xxxx0501.5xxx47,
  "uid": "hex_code",
  "id.orig_h": "10.x.x.11",
  "id.orig_p": 36299,
  "id.resp_h": "10.x.x.123",
  "id.resp_p": 53,
  "proto": "udp",
  "service": "dns",
  "duration": 0.00857415966797,
  "conn_state": "SF",
  "local_orig": true,
  "local_resp": true,
  "missed_bytes": 0,
  "history": "Dd",
  "orig_pkts": 1,
  "orig_ip_bytes": 74,
  "resp_pkts": 1,
  "resp_ip_bytes": 74
}
targeted jq output...
10.xxx.xxx.21 | 18.xx1.xx1.158 | 45.6606 <--time is shown cumulative duration

据我了解你想要完成的事情,这可能会朝着你的方向发展:

jq -sr '
  group_by([."id.orig_h", ."id.resp_h"])[]
  | [(first|."id.orig_h", ."id.resp_h"), (map(.duration)|add)]
  | @csv
' extract.json

说明:您的输入是对象流。使用 -s(或 --slurp)读取它们会将流变成数组。使用 group_by 我们将其转换为数组数组,分隔相等的值,此处作为两个 IP 字段的数组给出。接下来,对于外部数组的每个元素(组成员),我们仅构造第一个成员的两个 IP 字段的数组(这就足够了,因为所有其他成员都等于这方面),作为第三个值,我们 add 向上每个组成员 .duration 字段的值。最后,使用 @csv 将构建的数组转换为一行 CSV,由于初始 -r (--raw-output) 参数,它是原始打印的。

注意:我将 "ts": 1636xxxxx.41xxx34 之类的字段值视为对实际数字的混淆处理。但是,如果它是一个包含一些 x 个字符的字符串,那么字符串文字需要用引号 ("ts": "1636xxxxx.41xxx34") 引起来才能正确 JSON.


回答一个,如何过滤掉等于0的持续时间并按持续时间从高到低对剩余行进行排序

jq -sr '
  group_by([."id.orig_h", ."id.resp_h"]) | map(
    [(first|."id.orig_h", ."id.resp_h"), (map(.duration)|add)]
    | select(.[2] > 0)
  )
  | sort_by(-.[2])[]
  | @csv
' extract.json