使用jq一次删除多个键

时间:2016-03-25 20:09:17

标签: jq

我需要从一些JSON(使用jq)一次删除多个键,并且我试图了解是否有更好的方法来执行此操作,而不是每次都调用map和del。这是我的输入数据:

test.json

[
  {
    "label": "US : USA : English",
    "Country": "USA",
    "region": "US",
    "Language": "English",
    "locale": "en",
    "currency": "USD",
    "number": "USD"
  },
  {
    "label": "AU : Australia : English",
    "Country": "Australia",
    "region": "AU",
    "Language": "English",
    "locale": "en",
    "currency": "AUD",
    "number": "AUD"
  },
  {
    "label": "CA : Canada : English",
    "Country": "Canada",
    "region": "CA",
    "Language": "English",
    "locale": "en",
    "currency": "CAD",
    "number": "CAD"
  }
]

对于每个项目,我想删除数字,语言和国家/地区键。我可以用这个命令做到这一点:

$ cat test.json | jq 'map(del(.Country)) | map(del(.number)) | map(del(.Language))'

工作正常,我得到了所需的输出:

[
  {
    "label": "US : USA : English",
    "region": "US",
    "locale": "en",
    "currency": "USD"
  },
  {
    "label": "AU : Australia : English",
    "region": "AU",
    "locale": "en",
    "currency": "AUD"
  },
  {
    "label": "CA : Canada : English",
    "region": "CA",
    "locale": "en",
    "currency": "CAD"
  }
]

但是,我试图了解是否有jq方法指定要删除的多个标签,因此我不必拥有多个map(del())指令?

5 个答案:

答案 0 :(得分:16)

您可以提供要删除的路径的

$ cat test.json | jq 'map(del(.Country, .number, .Language))'

另外,请注意,您可能更愿意将您想要的密钥列入白名单,而不是将特定密钥列入黑名单:

$ cat test.json | jq 'map({label, region, locale, currency})'

答案 1 :(得分:7)

无需同时使用mapdel

您可以将多个路径传递给del,并用逗号分隔。

以下是使用“点式”路径符号的解决方案:

jq 'del( .[] .Country, .[] .number, .[] .Language )' test.json
  • 不需要引号(您可能会觉得引号更具可读性)
  • 不对路径进行分组(要求您重新输入.[],每个路径一次)

这里是一个使用“数组样式”路径符号的示例,它使您可以将路径与通用前缀合并,如下所示:

jq 'del( .[] ["Country", "number", "Language"] )' test.json
  • 在“最后一个共同祖先”(在本例中为顶级列表迭代器.[])下合并子路径

peak的答案使用mapdelpaths,尽管看来您也可以单独使用delpaths

jq '[.[] | delpaths( [["Country"], ["number"], ["Language"]] )]' test.json
  • 同时需要引号和单例数组
  • 要求您将其放回列表(带有方括号的开头和结尾)

总的来说,这里为了简洁起见,我会采用数组样式的表示法,但是知道做同一件事的多种方法总是很好的。

答案 2 :(得分:2)

delpaths也值得了解,也许不那么神秘:

map( delpaths( [["Country"], ["number"], ["Language"]] ))

答案 3 :(得分:1)

除了@ user3899165的答案外,我发现还可以从“子对象”中删除键列表。

example.json

{
    "a": {
        "b": "hello",
        "c": "world",
        "d": "here's",
        "e": "the"
    },
    "f": {
        "g": "song",
        "h": "that",
        "i": "I'm",
        "j": "singing"
    }
}

$ jq 'del(.a["d", "e"])' example.json

答案 4 :(得分:1)

路易斯在其answer中提到的“数组样式”和“点样式”表示法之间有更好的折衷。

del(.[] | .Country, .number, .Language)

jqplay


此表单还可用于从嵌套对象中删除键列表(请参阅russholio的answer):

del(.a | .d, .e)

暗示您还可以选择一个索引来删除以下项中的键:

del(.[1] | .Country, .number, .Language)

或多个:

del(.[2,3,4] | .Country,.number,.Language)

您可以使用range()函数删除范围(切片符号不起作用):

del(.[range(2;5)] | .Country,.number,.Language)  # same as targetting indices 2,3,4

一些注意事项:

map(del(.Country,.number,.Language))
# Is by definition equivalent to
[.[] | del(.Country,.number,.Language)]

如果键包含特殊字符或以数字开头,则需要用双引号将其引起来,例如:."foo$",否则为.["foo$"]