我已经使用jq进行了一些解析任务,几天前刚刚开始使用它并且正在享受它的多功能性,但我在下面概述的一项任务有点复杂而且我和#39;我在这个问题上与jq搏斗。
我有2个文件,两个文件都有类似的数据架构。文件A和B,以及我希望得到的输出,如下所示:
档案A:
[
{
"type": "hive-site",
"tag": 1507894175,
"properties" : {
"javax.jdo.option.ConnectionPassword" : "hortonworks1"
}
},
{
"type": "admin-properties",
"tag": 1507894175,
"properties": {
"fieldA": "valueA",
"fieldB": "valueB"
}
}
]
档案B:
[
{
"type": "hive-site",
"properties" : {
"javax.jdo.option.ConnectionPassword" : "hortonworks2"
}
},
{
"type": "admin-properties",
"properties": {
"fieldA": "valueA",
"fieldB": "valueB",
"fieldC": "valueC"
}
},
{
"type": "other-type",
"properties": {
"newFieldA": "valueA",
"newFieldB": "valueB"
}
}
]
结果:文件C(文件A为基础,文件B有修改)
[
{
"type": "hive-site",
"tag": 1507894175,
"properties" : {
"javax.jdo.option.ConnectionPassword" : "hortonworks2"
}
},
{
"type": "admin-properties",
"tag": 1507894175,
"properties": {
"fieldA": "valueA",
"fieldB": "valueB",
"fieldC": "valueC"
}
},
{
"type": "other-type",
"tag": NEW,
"properties": {
"newFieldA": "valueA",
"newFieldB": "valueB"
}
}
]
我想把所有配对都放在"属性"从文件B中将它们推送到文件A,更新现有属性对(如果存在),或将它们添加为自己的块(如图所示,使用" NEW"标记),如果不存在的话。
我找到了类似的答案(here和here),但没有一个能够根据我的目的进行修改。
谢谢!
答案 0 :(得分:0)
这是一个简洁明了的解决方案,基于以下事实:在jq中,如果X和Y是两个JSON对象,则表达式License: 20-214767 (Validity: 21/05/2022)20C-214769 (Validity: 21/05/2022)21-214768 (Validity: 21/05/2022)
优先于Y中的键。
首先,假设以下是combine.jq:
X + Y
以下调用将产生所需的结果:
def lookup($t):
$A[] | select(.type==$t) // {tag:"NEW"};
map( lookup(.type) + . )
如果你想要“一线”:
jq --argfile A A.json -f combine.jq B.json
答案 1 :(得分:0)
另一个 jq 解决方案(按.type
键分组):
jq --slurpfile f2 fileB '[$f2[0] + . | group_by(.type)[]
| if .[1] then .[1] + .[0] else .[0] end]' fileA
输出:
[
{
"type": "admin-properties",
"tag": 1507894175,
"properties": {
"fieldA": "valueA",
"fieldB": "valueB",
"fieldC": "valueC"
}
},
{
"type": "hive-site",
"tag": 1507894175,
"properties": {
"javax.jdo.option.ConnectionPassword": "hortonworks2"
}
},
{
"type": "other-type",
"properties": {
"newFieldA": "valueA",
"newFieldB": "valueB"
}
}
]
答案 2 :(得分:0)
这是一个解决方案,使用reduce从文件A创建临时查找表以及map来生成请求的输出,包括" NEW"文件B中的项目上的标记不存在于文件A中。
(reduce $A[] as $a({};.[$a.type]=$a)) as $t
| map(if $t[.type]==null then {tag:"NEW"}+. else $t[.type]*. end)
通过取消地图中的if
并使用// Alternative operator,可以更加简洁。例如
(reduce $A[] as $a({};.[$a.type]=$a)) as $t | map( ($t[.type]//{tag:"NEW"})*. )
示例运行(假定filter.jq
中的过滤器和FileA.json
和FileB.json
中的数据):
$ jq -M -f filter.jq --argfile A FileA.json FileB.json
[
{
"type": "hive-site",
"tag": 1507894175,
"properties": {
"javax.jdo.option.ConnectionPassword": "hortonworks2"
}
},
{
"type": "admin-properties",
"tag": 1507894175,
"properties": {
"fieldA": "valueA",
"fieldB": "valueB",
"fieldC": "valueC"
}
},
{
"tag": "NEW",
"type": "other-type",
"properties": {
"newFieldA": "valueA",
"newFieldB": "valueB"
}
}
]
以下过滤器还将包含文件A中不在文件B中的任何键(在注释中请求)。
(reduce $A[] as $a({};.[$a.type]=$a)) as $t # build lookup table
| map( ($t[.type]//{tag:"NEW"})*. ) # apply A to B
| (($t|keys_unsorted)-map(.type)) as $o # find keys in A not in B
| [$t[$o[]]] + . # add back those objects