所以我是 Shell 脚本新手,需要一些帮助。因此,在我的 CSV 文件中,我想查看 IP 和时间戳值是否以某种方式存在于 JSON 日志文件的行条目中,如果存在,则将该特定 JSON 日志条目返回到另一个文件。我试图使其通用,以便它适用于所有 IP 地址。示例 CSV 文件如下所示;
"clientip,""destip","dest_hostname","timestamp"
"127.0.0.1","0.0.0.0","randomhost","2023-09-09T04:18:22.542Z"
Json 日志文件中的示例行条目
{"log": "09-Sept-2023 rate-limit: info: client @xyz 127.0.0.1, "stream":"stderr", "time": 2023-09-09T04:18:22.542Z"}
这是我们希望在存在匹配时在 output.txt 文件中返回的 JSON 日志文件中的行。 JSON 文件没有像 CSV 那样的相同字段和组织(带有 clientip、destip、dest_hostname、时间戳,但我希望我仍然可以至少将 JSON 日志文件中的行返回到具有匹配项的新文件中)在 clientip 上(就像我们在“info: client @xyz 127.0.0.1”中看到的 127.0.0.1 一样),也许还有时间戳。
我已经尝试过,join file.csv xyz-json.log > output.txt
我也尝试过该awk
命令,但无济于事。我非常感谢您对此的帮助!
答案1
假设两个输入文件file.csv
和file.jsonl
分别正确格式化为 CSV 和 JSONL 文件,我们可以使用 Miller ( mlr
) 从 JSONL 文件中的键值中提取客户端 IP log
,然后使用将此作为关键。
两个测试输入文件(请注意,在本例中,CSV 文件中的引号是可选的):
"clientip","destip","dest_hostname","timestamp"
"127.0.0.1","0.0.0.0","randomhost","2023-09-09T04:18:22.542Z"
{"log": "09-Sept-2023 rate-limit: info: client @xyz 127.0.0.1", "stream": "stderr", "time": "2023-09-09T04:18:22.542Z"}
命令:
mlr --jsonl --from file.jsonl \
put '$clientip = splita($log," ")[-1]' then \
join -f file.csv -i csv -j clientip then \
cut -f log,stream,time
首先,通过按空格分割字段值并挑选出最后一个单词,clientip
在 JSONL 数据中创建一个字段。log
然后它执行一个关系内部联接将 JSONL 数据作为“右”数据集,将 CSV 数据作为“左”数据集进行操作。连接是用clientip
连接键来执行的。
最后,我们从连接产生的记录中删除原来不在 JSONL 数据中的所有字段(前两个步骤都向数据添加键)。
您是否还想在连接键中使用两个文件的时间戳,那么,由于两个数据集中的字段具有不同的名称,我认为最简单的方法是timestamp
使用time
JSONL 数据中键的值(基本上,您time
使用新名称复制数据),然后像这样加入:
mlr --jsonl --from file.jsonl \
put '$clientip = splita($log," ")[-1]; $timestamp = $time' then \
join -f file.csv -i csv -j clientip,timestamp then \
cut -f log,stream,time
上述两个命令中任何一个的输出都可以重定向到一个文件,并且根据问题中的(更正后的)数据,该输出将与 JSONL 输入数据相同。