这是我的两个json文件内容:
file1.json
{
"nodes": [
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-A"
},
{
"pm_addr": "192.100.0.6",
"name": "TB1-OSC-B"
},
{
"pm_addr": "192.100.0.7",
"name": "TB1-OSC-C"
}
]
}
file2.json
{
"nodes": [
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-D"
}
]
}
我想将file2.json的内容添加到file1.json,但在json对象之后:TB1-OSC-B,即第二个json条目。在这种情况下,该条目位于第二位置,但也可以位于其他任何位置。我的最终json文件应如下所示:
file3.json
{
"nodes": [
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-A"
},
{
"pm_addr": "192.100.0.6",
"name": "TB1-OSC-B"
},
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-D"
},
{
"pm_addr": "192.100.0.7",
"name": "TB1-OSC-C"
}
]
}
我使用的是jq版本:1.3,我无法对其进行升级。我尝试使用jq提供的add和= +参数。但这没有帮助。
感谢进阶
如果要将对象从file2.json
附加到nodes
数组,则非常简单:
jq -s '.[0].nodes += [ .[1].nodes[0] ] | .[0]' file1.json file2.json
输出:
{
"nodes": [
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-A"
},
{
"pm_addr": "192.100.0.6",
"name": "TB1-OSC-B"
},
{
"pm_addr": "192.100.0.7",
"name": "TB1-OSC-C"
},
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-D"
}
]
}
但是,由于要插入对象,因此变得更加棘手,因为jq
AFAIK不支持插入数组,仅支持前置和追加。
下面是一个相当复杂的示例,说明了如何通过将其拼接在其中:
parse.jq
# Find the desired index and store it as $n
(.[0].nodes | map(.name == "TB1-OSC-B") | index(true)) as $n |
# Splice the object from the second file into the first
.[0].nodes = .[0].nodes[0:($n|tonumber+1)] +
[ .[1].nodes[0] ] +
.[0].nodes[($n|tonumber+1):(.[0].nodes|length)] |
# Only output the now modified object from the first file
.[0]
像这样运行它:
jq -sf parse.jq file1.json file2.json
在这种情况下的输出:
{
"nodes": [
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-A"
},
{
"pm_addr": "192.100.0.6",
"name": "TB1-OSC-B"
},
{
"pm_addr": "192.100.0.4",
"name": "TB1-OSC-D"
},
{
"pm_addr": "192.100.0.7",
"name": "TB1-OSC-C"
}
]
}
清晰,可维护的解决方案的关键是具有适当的实用程序功能。
def insert_at(i; x): .[:i] + [x] + .[i:];
def indicesof(f):
. as $in
| range(0;length) | select( $in[.] | f );
def insert_after(f; x):
[indicesof(f)] as $ix
| if ($ix|length) > 0
then insert_at($ix[0]+1; x)
else . end;
jq 1.4允许更有效的解决方案,first/1
:
def insert_at($i; $x): .[:$i] + [$x] + .[$i:];
def indicesof(f):
. as $in
| range(0;length) | select( $in[.] | f );
def insert_after(f; $x):
(first(indicesof(f)) // null) as $i
| if $i then insert_at($i + 1; $x) else . end;
使用这些实用程序功能,可以直接表达给定问题的解决方案。例如,假设调用如下:
jq -s -f merge.jq file1.json file2.json
.[1].nodes[0] as $file2
| .[0]
| .nodes |= insert_after(.name == "TB1-OSC-B"; $file2)
可以根据详细要求轻松进行修改。