arrays - una - planeacion estrategica interna y externa
¿Cómo filtrar una matriz de objetos basados en valores en una matriz interna con jq? (2)
Dada esta entrada:
[
{
"Id": "cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b",
"Names": [
"condescending_jones",
"loving_hoover"
]
},
{
"Id": "186db739b7509eb0114a09e14bcd16bf637019860d23c4fc20e98cbe068b55aa",
"Names": [
"foo_data"
]
},
{
"Id": "a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19",
"Names": [
"jovial_wozniak"
]
},
{
"Id": "76b71c496556912012c20dc3cbd37a54a1f05bffad3d5e92466900a003fbb623",
"Names": [
"bar_data"
]
}
]
Estoy tratando de construir un filtro con
jq
que devuelva todos los objetos con
Id
s que
no
contengan "datos" en la matriz interna de
Names
, con la salida separada por una nueva línea.
Para los datos anteriores, el resultado que me gustaría es
cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19
Creo que estoy algo cerca de esto:
(. - select(.Names[] contains("data"))) | .[] .Id
pero el filtro de
select
no es correcto y no se compila (obtiene
error: syntax error, unexpected IDENT
).
¡Muy cerca!
En su expresión de
select
, debe usar una tubería (
|
) antes de
contains
.
Este filtro produce la salida esperada.
. - map(select(.Names[] | contains ("data"))) | .[] .Id
El jq Cookbook tiene un ejemplo de sintaxis.
Filtrar objetos según el contenido de una clave
Por ejemplo, solo quiero objetos cuya clave de género contenga "casa".
$ 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 pregunta cómo preservar la estructura JSON de la matriz, de modo que el resultado final sea una sola matriz JSON en lugar de una secuencia de objetos JSON.
La forma más simple es envolver toda la expresión en un constructor de matrices:
$ echo "$json" | jq -c ''[ .[] | select( .genre | contains("house")) ]''
[{"genre":"deep house"},{"genre":"progressive house"}]
También puede usar la función de mapa:
$ echo "$json" | jq -c ''map(select(.genre | contains("house")))''
[{"genre":"deep house"},{"genre":"progressive house"}]
map desempaqueta la matriz de entrada, aplica el filtro a cada elemento y crea una nueva matriz.
En otras palabras, el
map(f)
es equivalente a
[.[]|f]
.
Aquí hay otra solución que usa any/2
map(select(any(.Names[]; contains("data"))|not)|.Id)[]
con los datos de muestra y la opción
-r
produce
cb94e7a42732b598ad18a8f27454a886c1aa8bbba6167646d8f064cd86191e2b
a4b7e6f5752d8dcb906a5901f7ab82e403b9dff4eaaeebea767a04bac4aada19