Blog
JQ es una potente herramienta de línea de comandos diseñada para manipular y transformar datos JSON de forma eficiente. Tanto si eres un desarrollador, un analista de datos o un usuario que busca explorar datos estructurados en formato JSON, JQ puede ayudarte a realizar tus tareas de forma rápida y flexible.
Gracias a su enfoque basado en tuberías y filtros, JQ puede integrarse fácilmente en los flujos de trabajo existentes y combinarse con otras herramientas de línea de comandos. También ofrece una gran variedad de funciones avanzadas, como gestión de matrices, manipulación de cadenas, operaciones aritméticas y mucho más.
Para instalar JQ, ejecuta los siguientes comandos:
sudo apt-get update sudo apt install jq
Descarga el siguiente archivo ejecutando el siguiente comando en el terminal:
wget https://dst-de.s3.eu-west-3.amazonaws.com/bash_fr/people.json
El archivo contiene información sobre los personajes de Star Wars. Es un archivo JSON con la misma estructura que un diccionario Python. El archivo con el que vas a trabajar tiene una estructura especial: es una tabla de documentos. A continuación veremos algunas de las características esenciales que puedes utilizar con JQ:
Filtros
Los filtros se utilizan para acceder a un campo específico de un objeto. Para visualizar el documento con jq, basta con ejecutar el siguiente comando:
cat people.json | jq .
El . significa identidad, lo que significa que esto recupera el objeto como entrada y lo emite como salida. Deberías tener una salida como la siguiente:
[ { "birth_year": "19BBY", "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z", "eye_color": "blue", "films": [ "http://swapi.co/api/films/6/", "http://swapi.co/api/films/3/", "http://swapi.co/api/films/2/", "http://swapi.co/api/films/1/", "http://swapi.co/api/films/7/" ], "gender": "male", "hair_color": "blond", "height": "172", "homeworld": "http://swapi.co/api/planets/1/", "id": 1, "mass": "77", "name": "Luke Skywalker", "skin_color": "fair", "species": [ "http://swapi.co/api/species/1/" ], "starships": [ "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ], "url": "http://swapi.co/api/people/1/", "vehicles": [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ] } ]
Vemos aquí que tenemos un array de documentos. Para poder trabajar sobre él, necesitaremos añadir el filtro [], que permite recorrer el contenido de un array.
El rebanado es posible con jq como en Python.
Muestra los 5 primeros documentos del fichero.
Los filtros se utilizan para acceder a un campo específico de un objeto.
cat people.json | jq .[0:5]
La coma
Los filtros pueden concatenarse utilizando ,. Este operador permite aplicar varios filtros a la entrada estándar suministrada.
cat people.json | jq '.[].name, .[].height'
La salida será el conjunto de todos los nombres y tamaños disponibles en el archivo.
La tubería
Como en bash, es posible recuperar la salida de un comando y pasarla a un segundo filtro usando el |. Esto nos permite simplificar la escritura al encadenar filtros.
cat people.json | jq '.[] | .birth_year'
Fabricantes
Con JQ es posible construir objetos array o documento y almacenar en ellos los resultados de una consulta. Se trata de un procedimiento muy práctico para crear rápidamente nuevos documentos sin alterar el original.
Creemos tablas que contengan información clave sobre cada personaje:
cat people.json | jq .[] | jq '[.name, .birth_year, .mass, .height]'
La construcción de un documento es ligeramente diferente: todo lo que hay que hacer es poner {} llaves alrededor:
cat people.json | jq .[] | jq '{name, height, films: .films[]}''
Si desea recuperar campos que se encuentran en el primer nivel de sangría, puede simplemente especificar el nombre del campo. Esto tomará el nombre del campo del documento original y lo transferirá al nuevo documento. En cambio, para recuperar información de una tabla, deberá especificar un nuevo nombre de campo y un nuevo valor. Para recuperar valores de una tabla, no olvides poner el [] después del nombre del campo.
Construye un documento compuesto por los 10 caracteres y que contenga los siguientes campos: {nombre, año_nacimiento, masa, altura, especie, detalles: [mundo natal, vehículos, naves estelares]}
El resultado debería ser algo parecido a esto:
{ "name": "Luke Skywalker", "birth_year": "19BBY", "mass": "77", "species": "http://swapi.co/api/species/1/", "details": [ "http://swapi.co/api/planets/1/", [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ], "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ] }
cat people.json | jq '.[:10] | .[] | {name, birth_year, mass, species: .species[], details: [.homeworld, .vehicles, .starships[]]}'
Operadores y funciones integradas
Existe un conjunto de operadores y funciones integrados en JQ. Entre ellos se encuentran los operadores matemáticos de suma, resta, multiplicación y división. Se utilizan para realizar operaciones entre un escalar y un documento, o entre varios documentos.
Suma
Este operador actúa de forma diferente según el tipo de entrada que se le dé.
- Si las entradas son números, el resultado será una suma clásica
cat people.json | jq '.[0].height + .[1].height'
- Si las entradas son tablas, el resultado será la concatenación de éstas.
cat people.json | jq '.[0].species + .[1].species'
- Si las entradas son cadenas, el resultado es una cadena concatenada.
cat people.json | jq '.[0].name + .[1].name'
- Si las entradas son documentos, el resultado será una unión.
cat people.json | jq '.[] | {name, birth_year, mass} + {name, height}'
- Si los documentos tienen los mismos nombres de clave, el valor a la derecha del + se mantendrá en el resultado.
cat people.json | jq '.[0] + .[1]'
En el ejemplo anterior, acabamos de sumar los documentos, pero como son exactamente iguales, sólo conservamos los valores del documento situado a la derecha del +.
Resta
Este operador puede utilizarse para restar entre dos números, así como para eliminar valores de una matriz. Ten en cuenta que la sintaxis especifica que sólo es posible eliminar ocurrencias entre matrices.
cat people.json | jq '.[0].films - ["http://swapi.co/api/films/6/", "http://swapi.co/api/films/7/"]'
Multiplicación
La multiplicación con JQ también tiene varias propiedades especiales. En primer lugar, es posible realizar la multiplicación clásica de dos números enteros. También es posible multiplicar un número por una cadena. En este último caso, las cadenas se concatenan un determinado número de veces.
cat people.json | jq '.[10].id * 15' cat people.json | jq '.[0].name * 3'
La salida del comando anterior debería ser:
165 "Luke SkywalkerLuke SkywalkerLuke Skywalker"
División
La división tiene un efecto muy práctico en las cadenas. Mientras que es posible dividir números entre sí (excepto, por supuesto, la división 0), también es posible separar una cadena con un segundo. En el siguiente ejemplo, vamos a separar una cadena de caracteres con un separador que es a su vez una cadena de caracteres:
cat people.json | jq '.[0].name / "e"'
El resultado es el siguiente:
[ "Luk", "Skywalk", "r" ]
Como puedes ver, la cadena inicial Luke Skywalker se ha dividido en 3 partes utilizando el separador e.
Función Group By integrada
La función group_by se utiliza para agrupar documentos con la misma clave en diferentes tablas.
cat people.json | jq 'group_by(.eye_color)'
La salida es una tabla formada por varias tablas que agrupan documentos con el mismo atributo eyecolor. Es posible contar el número de modalidades del atributo eyecolor y calcular el número de ocurrencias:
cat people.json | jq 'group_by(.eye_color)[] | {gender: .[0].eye_color, count: .|length}'
Deberías obtener el siguiente resultado:
{ "eye_color": "black", "count: 10 } { "eye_color": "blue", "count: 19 } { "eye_color": "blue-gray", "count: 1 } { "eye_color": "brown", "count: 20 } { "eye_color": "dark", "count: 1 } { "eye_color": "gold", "count: 1 } { "eye_color": "green, yellow", "count: 1 } { "eye_color": "hazel", "count: 2 } { "eye_color": "orange", "count: 8 } { "eye_color": "pink", "count: 1 } { "eye_color": "red", "count: 5 } { "eye_color": "red, blue", "count: 1 } { "eye_color": "unknown", "count: 1 } { "eye_color": "white", "count: 1 } { "eye_color": "yellow", "count: 11 }
Aquí hemos utilizado la función incorporada length, que devuelve la longitud de un objeto. En nuestro caso, la función se aplicará a todas las matrices y contará el número de documentos que contienen.
Hay muchas más funciones y operadores en JQ. Se trata de una herramienta muy potente para acelerar las fases de transformación de una cadena de extracción, transformación y carga de datos, también conocida como `ETL’.