如何将 jq 用作大型 json 文件的 SED(可选地使用映射 table)
How to use jq as SED for large json file (optionally with a mapping table)
我有一个很大的 json 文件,其中包含 json 文件中的多个 IP。我想替换 json 文件中的特定 IP 地址(无需将输出写入新文件)。等效的 SED 命令是 sed -i 's/old_ip/new_ip/g'
结构如下(json 文件中的单个 json 条目):
{
"destination":{
"port":53,
"bytes":100,
"ip":"1.1.1.1"
},
"source":{
"port":54894,
"bytes":84,
"ip":"10.1.1.49",
},
"related":{
"ip":"10.5.5.45"
},
"event":{
"code":"0000000013",
"action":"accept",
"type":[
"allowed",
"connection",
"end",
"protocol"
],
"outcome":"success"
},
"@timestamp":"2021-08-29T04:47:10.000+02:00"
}
我现在有两个问题无法解决。
问题一:
我想用相应的 IP 地址替换每个 IP。所以想象一下我想用 10.10.10.10
替换 IP 10.1.1.49
我知道我可以使用命令 jq '(.. | .ip?)' | select(.ip == "10.2.1.49")| .ip |= "10.10.10.10"'
但不幸的是,这只是输出新 IP,而不是像 SED 那样在文件中替换它(这是指我在网上找到的所有解决方案)。
问题二:
现在假设我有一个具有以下结构的映射 table (mapping.json):
{
"10.2.1.49":"10.10.10.10",
"10.15.15.15":"10.10.10.10"
}
我能否提供此映射 table 并将其与 jq 结合起来以进行查找和替换?我觉得这在 jq 中是不可能的,这意味着我需要弄清楚我的第一个问题,然后编写一个 bash 脚本。有人通过使用 --sluprfile 提出了类似的问题 ()。但显然我不能使用此 link 中的解决方案,因为需要 ID 或唯一的选择值,而我的 json.
中没有
是否有简单的解决方案,或者我应该将 SED 与 shellscript 结合使用?
谢谢
关于问题 1
您可以使用
更新相关IP地址
jq '(.. | .ip? | select(. == "10.1.1.49")) |= "10.10.10.10"'
{
"destination": {
"port": 53,
"bytes": 100,
"ip": "1.1.1.1"
},
"source": {
"port": 54894,
"bytes": 84,
"ip": "10.10.10.10"
},
"related": {
"ip": "10.5.5.45"
},
"event": {
"code": "0000000013",
"action": "accept",
"type": [
"allowed",
"connection",
"end",
"protocol"
],
"outcome": "success"
},
"@timestamp": "2021-08-29T04:47:10.000+02:00"
}
但是您不能 像使用sed -i
那样更新文件——至少不能只使用标志。但是,使用临时文件或 sponge
等可以正常工作。
关于问题 2
读入映射,例如使用 --argfile
并使用查找结合替代运算符 //
进行更新以回退到原始值(如果它不存在于映射
中)
jq --argfile mapping mapping.json '(.. | .ip? // empty) |= ($mapping[.]? // .)'
我有一个很大的 json 文件,其中包含 json 文件中的多个 IP。我想替换 json 文件中的特定 IP 地址(无需将输出写入新文件)。等效的 SED 命令是 sed -i 's/old_ip/new_ip/g'
结构如下(json 文件中的单个 json 条目):
{
"destination":{
"port":53,
"bytes":100,
"ip":"1.1.1.1"
},
"source":{
"port":54894,
"bytes":84,
"ip":"10.1.1.49",
},
"related":{
"ip":"10.5.5.45"
},
"event":{
"code":"0000000013",
"action":"accept",
"type":[
"allowed",
"connection",
"end",
"protocol"
],
"outcome":"success"
},
"@timestamp":"2021-08-29T04:47:10.000+02:00"
}
我现在有两个问题无法解决。
问题一: 我想用相应的 IP 地址替换每个 IP。所以想象一下我想用 10.10.10.10
替换 IP 10.1.1.49我知道我可以使用命令 jq '(.. | .ip?)' | select(.ip == "10.2.1.49")| .ip |= "10.10.10.10"'
但不幸的是,这只是输出新 IP,而不是像 SED 那样在文件中替换它(这是指我在网上找到的所有解决方案)。
问题二: 现在假设我有一个具有以下结构的映射 table (mapping.json):
{
"10.2.1.49":"10.10.10.10",
"10.15.15.15":"10.10.10.10"
}
我能否提供此映射 table 并将其与 jq 结合起来以进行查找和替换?我觉得这在 jq 中是不可能的,这意味着我需要弄清楚我的第一个问题,然后编写一个 bash 脚本。有人通过使用 --sluprfile 提出了类似的问题 (
是否有简单的解决方案,或者我应该将 SED 与 shellscript 结合使用? 谢谢
关于问题 1
您可以使用
更新相关IP地址jq '(.. | .ip? | select(. == "10.1.1.49")) |= "10.10.10.10"'
{
"destination": {
"port": 53,
"bytes": 100,
"ip": "1.1.1.1"
},
"source": {
"port": 54894,
"bytes": 84,
"ip": "10.10.10.10"
},
"related": {
"ip": "10.5.5.45"
},
"event": {
"code": "0000000013",
"action": "accept",
"type": [
"allowed",
"connection",
"end",
"protocol"
],
"outcome": "success"
},
"@timestamp": "2021-08-29T04:47:10.000+02:00"
}
但是您不能 像使用sed -i
那样更新文件——至少不能只使用标志。但是,使用临时文件或 sponge
等可以正常工作。
关于问题 2
读入映射,例如使用 --argfile
并使用查找结合替代运算符 //
进行更新以回退到原始值(如果它不存在于映射
jq --argfile mapping mapping.json '(.. | .ip? // empty) |= ($mapping[.]? // .)'