2017-03-15 20 views
1

我已经阅读了几乎所有我能找到的问题与相同的一般前提下,我已经接近三个不同的时间,但我不能使这项工作。追加新的密钥对JSON文件与jq

给定一个名为parameters.json的JSON文件,它带有这样的密钥对; (缩短共享的目的)

[ 
    { 
    "ParameterKey": "Foo1", 
    "ParameterValue": "Bar1" 
    }, 
    { 
    "ParameterKey": "Foo2", 
    "ParameterValue": "Bar2" 
    } 
] 

我要添加另一个密钥对,说

{ 
    "ParameterKey": "Foo3", 
    "ParameterValue": "Bar3" 
    } 

所以我最终喜欢

[ 
    { 
    "ParameterKey": "Foo1", 
    "ParameterValue": "Bar1" 
    }, 
    { 
    "ParameterKey": "Foo2", 
    "ParameterValue": "Bar2" 
    }, 
    { 
    "ParameterKey": "Foo3", 
    "ParameterValue": "Bar3" 
    } 
] 

使用案例文件&尝试

我正在写一个bash脚本来复制和更新AWS的参数文件 - 这是密钥对进来。我们有一个新的密钥对,当它们被复制时,需要将它添加到任何现有的文件中。我可以得到如果/然后做得很好,它实际上是增加了一个新的密钥对,这对我来说很困难。

一吨的google搜索,我结束了这个笨重的解决办法,我真的不明白,并同时生成密钥对蛮好的,不添加回parameters.json

item='{"ParameterKey": "RTSMSnapshotID"}' 

jq --argjson item "$item" '$item + {"ParameterValue": ""}' parameters.json 

我在命令行中将密钥对正确地打印回给我,所以我想添加| sponge parameters.json,但那会给我一个空文件。

我也考虑过一个sed解决方法,修剪文件的最后一行,然后附加新的密钥对(和EOF),但当然sed不能很好地适应换行符,并且我无法使其工作。

我很喜欢在bash和jq中使用任何东西的解决方案。我仍然是一个bash/jq noob,所以我对此有详细的解释。

回答

2

使用argjson的想法是正确的,但语法是如下的jq-1.5

jq --argjson obj '{ "ParameterKey": "Foo3", "ParameterValue": "Bar3" }' '. + [$obj]' < json 
[ 
    { 
    "ParameterKey": "Foo1", 
    "ParameterValue": "Bar1" 
    }, 
    { 
    "ParameterKey": "Foo2", 
    "ParameterValue": "Bar2" 
    }, 
    { 
    "ParameterKey": "Foo3", 
    "ParameterValue": "Bar3" 
    } 
] 

检查jq-documentation有关++=运营商的更多信息。

我不知道的方式jq本身要做到这一点,但您可以使用一个整洁bash伎俩要做到这一点,

jq --argjson obj '{ "ParameterKey": "Foo3", "ParameterValue": "Bar3" }' '. + [$obj]' <json> temp && mv temp json 
+0

这确实增加了新的密钥对预期(谢谢!),但打印输出到命令行。我如何将它重新输入'parameters.json'? – Alex

+1

在jq常见问题页面(https://github.com/stedolan/jq/wiki/FAQ)上,搜索:-i – peak

+1

以防万一有人需要使用此功能 - 事实证明,您可以添加'|海绵parameters.json'如果你有工具安装一个简单的解决方法。 – Alex

1

如果你有一个文件,一个JSON阵列(说parameters.json) ,以及一个或多个附加文件(比如说文件* .json),这些文件需要附加到第一个文件中的数组,并且如果您想覆盖第一个文件,则这是一个相当狡猾的解决方案,但需要jq 1.5或更高版本:

$ jq 'reduce inputs as $in (.; . + [$in])' parameters.json file*.json | 
    sponge parameters.json 

注意th在使用这种方法时,每个辅助文件中的每个顶层JSON实体都将分别附加到数组中。

是什么让这个有点狡猾的是inputs这里没有使用-n选项。

既然你提到bash,请注意,如果任何的“文件*以.json”的来源是一个过程,你可以使用<(...),而不是指定一个文件名,如:

$ jq 'reduce inputs as $in (.; . + [$in])' parameters.json <(curl -Ss ...) | 
    sponge parameters.json 

如果你不”吨有sponge,那么你可以使用这个成语:

jq ..... > OUT && mv IN OUT 
+0

我特别需要一个没有中间文件的解决方案,因为这个过程发生在Jenkins,并且一旦涉及文件,它就会混乱工作区或需要git签出。不过,我赞成答案;可能对别人使用不同用例有用。 – Alex

+0

@Alex你可以使用<(...)? – peak