【问题标题】:changing the json using jq in bash在 bash 中使用 jq 更改 json
【发布时间】:2017-08-31 05:27:47
【问题描述】:

我有以下 json

{
    "name" : "qwerty",
    "values" :[
    {
        "field1" : [
            "val1"
            ],
        "field2" : [
            "val2"
            ],
        "name1" : [["a", "b"], ["c", "d"]]
    },
    {
        "field1" : [
            "val3"
            ],
        "field2" : [
            "val4"
            ],
        "name1" : [["a", "b"], ["c", "d"]]
    },
    {
        "field1" : [
            "val5"
            ],
        "field2" : [
            "val6"
            ],
         "name1" : [["a", "b"], ["c", "d"]]
    }
    ]
}

我需要在bash中使用jq将上面的json改成下面的

{
    "name" : "qwerty",
    "values" :[
    {
        "field1" :  "val1",
        "field2" :  "val2",
        "new_name" : [["a", "b"], ["c", "d"]]
    },
    {
        "field1" : "val3",
        "field2" : "val4",
        "new_name" : [["a", "b"], ["c", "d"]]
    },
    {
        "field1" : "val5",
        "field2" : "val6",
        "new_name" : [["a", "b"], ["c", "d"]]
    }
    ]

}

这里我面临以下问题:

我尝试用标记值解析内部 json 并将 '[' ']' 替换为空格,但是,当我尝试将“值”以列表的形式放入变量中时,jq 正在美化然后显示每个新行作为数组的一个元素。

values 数组中的内部 json 数量不固定。

请有人帮我制定要在 bash 中运行的 jq 语句以进行所需的更改。

【问题讨论】:

  • @fedorqui thnx 指出这一点,更正了问题
  • 您知道要更改的具体是.values[].field1.values[].field2,还是应该折叠为单个值的任何单例列表?
  • 是的,“field1,field2,name”在每个 json 中都是固定的。但是json的数量不固定。
  • @vamsi 我已经编辑了我的答案,现在应该没问题
  • 抱歉重新提出问题。我的要求有一个轻微的变化,我想知道如果我们没有固定字段的数量是否可以做到这一点。即“field1,field2,name”在每个json中也不是固定的。

标签: json bash jq


【解决方案1】:

这应该有效;我不确定是否有办法将分配重构为field1field2

jq '.values[] |= (.field1=.field1[0] | .field2=.field2[0])' tmp1.json

【讨论】:

  • 另一种选择是使用新值创建一个对象并将其合并。但我认为这比作业更丑陋,而且可能更具破坏性。
  • 仅基于名称,我认为foreach 可能是相关的,但我似乎无法理解它是如何工作的。我所能做的就是想出像jq '.values[] |= (foreach ["field1", "field2"] as $f (empty;.[$f]=.[$f][0];empty))' tmp1.json 这样至少符合要求的东西;它不产生任何输出。
  • 在我看来,foreachreduce 类似,但多了一个提取部分。因此,在您评论中的示例中,您使用空值进行了初始化,并尝试为其分配值。但是 empty 是空的,因此每次迭代都不会产生任何结果。然后对于提取部分,您提取的是空的,因此没有任何内容。使用这种方法,您可以坚持使用reduce(稍作调整):.values[] |= reduce ("field1", "field2") as $f (.;.[$f]=.[$f][0])
  • 好的,很好。我想我现在对reduce 的理解要好一些了。
  • 做了一些思考,这里有另一种可以修改多个值的方法:.values[] |= (.["field1", "field2"] |= .[0])
【解决方案2】:

下面的 sn-p 应该做你想做的事:

jq '{
    "name": .name, 
    "values": [ 
        {
            "field1" : .values[0].field1[0], 
            "field2" : .values[0].field2[0],
            "New_name": .values[0].name1  
        },
        {
            "field1" : .values[1].field1[0],
            "field2" : .values[1].field2[0],
            "new_name" : .values[1].name1
        },
        {
            "field1" : .values[2].field1[0],
            "field2" : .values[2].field2[0],
            "new_name" : .values[2].name1
        }
    ]  
}' < /tmp/input.json

编辑

由于对象的数量不固定,下面的 sn-p 就可以了:

jq '{ 
        "name" : .name,
        "values" : [
                .values[] as $in | 
                { 
                        "field1" : $in.field1[0],
                        "field2" : $in.field2[0],
                        "new_name" : $in.name1 
                }
        ]

}' < /tmp/input.json

【讨论】:

  • 感谢您的快速响应。但是,values 数组中的内部 json 的数量是不固定的。
【解决方案3】:

这是另一种解决方案。

  .values |= map({
     field1:   .field1[0],
     field2:   .field2[0],
     new_name: .name1
  })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多