更简洁的 jq 代码,用于从文件中获取每个值并放置在另一个值中



我的目标是获取一组键对的每个值,并将每个值插入到另一个文件中。我可以逐行执行此操作,但是有没有一种更干净的方法可以一次添加它们?

我有一个 aws 查询的结果,它给了我以下名为vpc.json的文件(去除了敏感信息);

[
{
"Description": "Client VpcId", 
"OutputKey": "VpcId", 
"OutputValue": "vpc-a12345"
}, 
{
"OutputKey": "ServiceSubnet1", 
"OutputValue": "subnet-b12345"
}, 
{
"OutputKey": "PublicSubnet1", 
"OutputValue": "subnet-c12345"
}, 
{
"OutputKey": "ServiceSubnet0", 
"OutputValue": "subnet-d12345"
}, 
{
"OutputKey": "PublicSubnet0", 
"OutputValue": "subnet-e12345"
}
]

我希望每个值都以parameters.json结尾,它已经有一堆其他键对,最终文件看起来像;

[
{
...
},
{
"ParameterKey": "VpcId",
"ParameterValue": "vpc-a12345"
},
{
"ParameterKey": "ServiceSubnet0",
"ParameterValue": "subnet-b12345"
},
{
"ParameterKey": "ServiceSubnet1",
"ParameterValue": "subnet-c12345"
},
{
"ParameterKey": "PublicSubnet0",
"ParameterValue": "subnet-d12345"
},
{
"ParameterKey": "PublicSubnet1",
"ParameterValue": "subnet-e12345"
}
]

现在,我可以使用以下代码"轻松"实现此目的。这将是VpcId对所需的代码片段,这意味着我必须复制它 x5,每个密钥对一个。

代码检查密钥对是否已存在,如果不存在,则添加它(必需,因为这需要向后兼容旧文件)。然后,它从 vpc 文件中获取相关值,并将其放置在参数文件中。

if ! grep -q "VpcId" parameters.json
then
jq --argjson obj '{ "ParameterKey": "VpcId", "ParameterValue": "" }' '. += [$obj]' <parameters.json | sponge parameters.json
fi
keyVpc=$(jq -r '.[] | select(.OutputKey=="VpcId") | .OutputValue' < vpc.json)
jq --arg keyVpc "$keyVpc" '(.[] | select(.ParameterKey == "VpcId") | .ParameterValue) |= $keyVpc' ${parameters.json | sponge parameters.json

我必须想象有一种更好的方法来做到这一点,不需要相同三行的 5 个副本。键将始终使用相同的名称,但值将更改。

为了清楚起见,我们首先定义一个 jq 帮助程序函数来修改键/值对:

def munge: {ParameterKey: .OutputKey, ParameterValue: .OutputValue};

我们还假设 vpc.json 的内容可用作 jq 变量$vpc -- 例如,可以按如下所示完成此操作。

然后,可以通过此 jq 过滤器执行更新:

. + (($vpc | map(munge)) - .)

以下调用是几种可能性之一,但具有不需要最新 jq 版本的优点:

jq -f vpc.jq --argfile vpc vpc.json parameters.json

变化

根据详细要求,可能会有更有效的变化。 例如,如果键/值对的顺序不重要:

(. + ($vpc | map(munge))) | unique

相反,为了避免 ($vpc|map(munge)) 中的重复,同时保留顺序:

reduce ($vpc[] | munge) as $new
(.; if index($new) then . else . + [$new] end)

相关内容

最新更新