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

时间:2017-05-30 14:30:40

标签: json bash 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个相同的三行副本。键将始终是相同的名称,但值将更改。

1 个答案:

答案 0 :(得分:3)

为清楚起见,我们首先定义一个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)