试图在 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
前言:企业网络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.
回答一个
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