Filtrado de solicitudes JSON con JQ y scripts bash

Filtrado de solicitudes JSON con JQ y scripts bash

Estoy solicitando un JSON de Twitch con: curl --silent -H 'Accept: application/vnd.twitchtv.v3+json' -X GET https://api.twitch.tv/kraken/streams/$1donde $1está el input que envío para mi función.

Ahora lo que pretendo es filtrar el JSON canalizando esto después del curl: | jq '.stream.channel.something' estoy tratando de obtener 3 valores de cadena diferentes a través del filtrado jq. Puedo lograr llevarlos a este nivel:

{
    "first": "lor"
    "second": "em"
    "third": "ipsum"
}

¿Manera de operar con ellos dentro del código?


Las alternativas que se me han ocurrido son:

  1. Cree la salida del rizo, fíltrelo y luego elimínelo.
  2. Envíe 3 solicitudes cURL - (¿Acaparador de rendimiento inútil?).

Respuesta1

Como dije, no sé mucho sobre json o jq, pero no pude lograr que jq analizara el resultado de muestra de:

{
    "first": "lor"
    "second": "em"
    "third": "ipsum"
}

parse error: Expected separator between values at line 3, column 12

Entonces convertí la entrada en:

{
  "stream" : {
    "channel" : {
      "something" : {
        "first": "lor",
        "second": "em",
        "third": "ipsum"
      }
    }
  }
}

... basado en lo que deduje de tu llamada a jq. Con suerte, eso es similar a lo que genera el comando curl.

Si es así, entonces parece que esta secuencia te proporciona lo que deseas:

# this is just your original curl command, wrapped in command substitution,
# in order to assign it to a variable named 'output':
output=$(curl --silent -H 'Accept: application/vnd.twitchtv.v3+json' -X GET https://api.twitch.tv/kraken/streams/$1)

# these three lines take the output stream from above and pipe it to
# separate jq calls to extract the values; I added some pretty-printing whitespace
first=$( echo "$output" | jq '.["stream"]["channel"]["something"]["first"]' )
second=$(echo "$output" | jq '.["stream"]["channel"]["something"]["second"]')
third=$( echo "$output" | jq '.["stream"]["channel"]["something"]["third"]' )

Con los resultados:

$ echo $first
"lor"
$ echo $second
"em"
$ echo $third
"ipsum"

Respuesta2

Suponiendo que su archivo es JSON válido (que los datos de la pregunta no lo son):

{
  "first": "lor",
  "second": "em",
  "third": "ipsum"
}

Puede utilizar jqpara crear tres asignaciones a partir de esto, que puede evaluar de forma segura en el shell:

eval "$(
    jq -r '
        @sh "first=\(.first)",
        @sh "second=\(.second)",
        @sh "third=\(.third)"' file.json
)"

El @shoperador en jqgenerará asignaciones en el formulario first='lor'para que el shell las evalúe.

Para el bashshell, también puedes crear una asignación de matriz:

eval "$(
    jq -r '@sh "array=(\([.first, .second, .third]))"' file.json
)"

Aquí, el jqcomando generaría algo como array=('lor' 'em' 'ipsum'), que cuando se evaluara bashcrearía la matriz llamada arraycon el contenido dado.

Podría usar la jqdeclaración @sh "array=(\([.[]]))"para crear una matriz de los valores de todas las claves, asumiendo que cada valor es un escalar.

información relacionada