【问题标题】:Select objects based on value of variable in object using jq使用jq根据对象中变量的值选择对象
【发布时间】:2013-09-06 16:21:30
【问题描述】:

我有以下 json 文件:

{
    "FOO": {
        "name": "Donald",
        "location": "Stockholm"
    },
    "BAR": {
        "name": "Walt",
        "location": "Stockholm"
    },
    "BAZ": {
        "name": "Jack",
        "location": "Whereever"
    }
}

我正在使用 jq 并希望获取“位置”为“斯德哥尔摩”的对象的“名称”元素。

我知道我可以得到所有的名字

cat json | jq .[] | jq ."name"
"Jack"
"Walt"
"Donald"

但我不知道如何只打印某些对象,给定子键的值(这里:"location" : "Stockholm")。

【问题讨论】:

    标签: json bash select jq


    【解决方案1】:

    改编自Processing JSON with jq 上的这篇文章,您可以像这样使用select(bool)

    $ jq '.[] | select(.location=="Stockholm")' json
    {
      "location": "Stockholm",
      "name": "Walt"
    }
    {
      "location": "Stockholm",
      "name": "Donald"
    }
    

    【讨论】:

    • 我如何获得父 'FOO'、'BAR'、'BAZ'?
    • 我不确定你所说的父母是什么意思(你是说钥匙吗?)......它只是jq 'keys' json。如果您的意思是过滤器后的键,给"FOO" "BAR",使用this answer 并使用.key 而不是[.key, .value.name]
    【解决方案2】:

    要获取仅包含名称的流:

    $ jq '.[] | select(.location=="Stockholm") | .name' json
    

    产生:

    "Donald"
    "Walt"
    

    要获得对应的(键名,“名称”属性)对流,请考虑:

    $ jq -c 'to_entries[]
            | select (.value.location == "Stockholm")
            | [.key, .value.name]' json
    

    输出:

    ["FOO","Donald"]
    ["BAR","Walt"]
    

    【讨论】:

    • 他想要基于位置的整个对象:“我不知道如何只打印某些对象,给定子键的值”
    • 选择后不需要管道:$ jq '.[] | select(.location=="Stockholm").name' json
    • 使name 键变量(使用带有$1 作为参数的shell 函数)不起作用:termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'。我称之为cool_fn Name1。但是,这可行:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
    • Here 是解决方案,如果你喜欢它的变量。
    • @Fo - 在问题的主体中,OP 非常具体:'我想获取对象的“名称”元素'。显然,在 Q 的标题中,OP 使用了一般意义上的“对象”一词。
    【解决方案3】:

    我有一个类似的相关问题:如果您想要返回原始对象格式(带有键名,例如 FOO、BAR)怎么办?

    Jq 提供to_entriesfrom_entries 来实现对象和键值对数组之间的转换。与map 一起选择

    这些函数在对象和键值数组之间转换 对。如果给 to_entries 传递了一个对象,那么对于每个 k:v 中的条目 输入,输出数组包括 {"key": k, "value": v}。

    from_entries 进行相反的转换,而 with_entries(foo) 是 to_entries 的简写 |地图(foo) | from_entries,对做有用的 对对象的所有键和值进行一些操作。 from_entries 接受键、键、名称、名称、值和值作为键。

    jq15 < json 'to_entries | map(select(.value.location=="Stockholm")) | from_entries'
    
    {
      "FOO": {
        "name": "Donald",
        "location": "Stockholm"
      },
      "BAR": {
        "name": "Walt",
        "location": "Stockholm"
      }
    }
    

    使用with_entries 速记,这变成:

    jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
    {
      "FOO": {
        "name": "Donald",
        "location": "Stockholm"
      },
      "BAR": {
        "name": "Walt",
        "location": "Stockholm"
      }
    }
    

    【讨论】:

    • 一直困扰我的一件事是,您需要记住,在使用with_entries() 时,您通常还希望在select 子句中也使用.value。这是因为to_entries 宏将给定条目转换为.key.value 对,with_entries 也会发生这种情况。
    【解决方案4】:

    只需将这个作为完整的复制粘贴到 shell 中试试,你就会掌握它。

    # create the example file to  be working on .. 
    cat << EOF > tmp.json
    [  
     { "card_id": "id-00", "card_id_type": "card_id_type-00"},
     {"card_id": "id-01", "card_id_type": "card_id_type-01"},
     {  "card_id": "id-02", "card_id_type": "card_id_type-02"}
    ]
    EOF
    
    
    # pass the content of the file to the  jq query, which gets the array of objects
    # and select the attribute named "card_id" ONLY if its neighbour attribute
    # named "card_id_type" has the "card_id_type-01" value.
    # jq -r means give me ONLY the value of the jq query no quotes aka raw
    jq -r '.[]| select (.card_id_type == "card_id_type-01")|.card_id' <tmp.json
    id-01
    

    或使用 aws cli 命令

     # list my vpcs or
     # list the values of the tags which names are "Name" 
     aws ec2 describe-vpcs | jq -r '.| .Vpcs[].Tags[]|select (.Key == "Name") | .Value'|sort  -nr
    

    请注意,您可以在过滤阶段和选择阶段在层次结构中上下移动:

     kubectl get services --all-namespaces -o json | jq -r \
       '.items[] | select( .metadata.name | contains("api-doc")) | \
      { name: .metadata.name, ns: .metadata.namespace , nodePort: .spec.ports[].nodePort, port: .spec.ports[].port}'
    

    【讨论】:

    • 我不明白为什么这个投票最少且未被接受的评论位于顶部?
    • 检查您的个人设置以对答案进行排序......它可能基于上次修改的 ts ;o)
    猜你喜欢
    • 2023-01-09
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 2016-04-25
    相关资源
    最近更新 更多