How to filter an array of objects based on values in an inner array with jq?

前端 未结 2 1340
你的背包
你的背包 2020-11-28 18:20

Given this input:

[
  {
    \"Id\": \"cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b\",
    \"Names\": [
      \"condescending_jones\",
            


        
相关标签:
2条回答
  • 2020-11-28 18:59

    Very close! In your select expression, you have to use a pipe (|) before contains.

    This filter produces the expected output.

    . - map(select(.Names[] | contains ("data"))) | .[] .Id
    

    The jq Cookbook has an example of the syntax.

    Filter objects based on the contents of a key

    E.g., I only want objects whose genre key contains "house".

    $ json='[{"genre":"deep house"}, {"genre": "progressive house"}, {"genre": "dubstep"}]'
    $ echo "$json" | jq -c '.[] | select(.genre | contains("house"))'
    {"genre":"deep house"}
    {"genre":"progressive house"}
    

    Colin D asks how to preserve the JSON structure of the array, so that the final output is a single JSON array rather than a stream of JSON objects.

    The simplest way is to wrap the whole expression in an array constructor:

    $ echo "$json" | jq -c '[ .[] | select( .genre | contains("house")) ]'
    [{"genre":"deep house"},{"genre":"progressive house"}]
    

    You can also use the map function:

    $ echo "$json" | jq -c 'map(select(.genre | contains("house")))'
    [{"genre":"deep house"},{"genre":"progressive house"}]
    

    map unpacks the input array, applies the filter to every element, and creates a new array. In other words, map(f) is equivalent to [.[]|f].

    0 讨论(0)
  • 2020-11-28 19:15

    Here is another solution which uses any/2

    map(select(any(.Names[]; contains("data"))|not)|.Id)[]
    

    with the sample data and the -r option it produces

    cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
    a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19
    
    0 讨论(0)
提交回复
热议问题