jq
Filtra, ordena y da formato a datos JSON desde la terminal.
Toma un JSON y te devuelve la parte que le pidas: un campo, una lista ya filtrada, un valor por renglón. Lo usas cuando un comando entrega JSON, como las APIs que consultas con curl, y quieres leerlo rápido, buscar algo en particular o pasarlo limpio a otro programa. En Debian 13 / Ubuntu 24.04 no viene instalado por defecto: sudo apt install jq.
jq [opciones] FILTRO [archivo...]Despiece
6 ejemplosVer un JSON bien formateado
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | . | Valor | El filtro. El punto solo significa 'pasa el dato tal cual', pero al imprimirlo jq lo deja indentado y legible. |
| 3 | datos.json | Argumento | El archivo de entrada; también puedes escribir el JSON entre comillas o ponerlo en un pipe. |
jq sin filtro devuelve lo mismo que le diste, pero con formato: una clave por renglón y sangría. Sirve para leer de un vistazo un JSON que venía todo pegado, por ejemplo la respuesta de curl.
Sacar un solo valor
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | -r | Opción | Raw output: imprime el texto sin las comillas que jq pondría para que la salida siga siendo JSON válido. |
| 3 | '.servidor' | Valor | El filtro. El punto accede a la clave servidor; las comillas protegen el texto de la terminal. |
| 4 | config.json | Argumento | El archivo de donde sale el valor. |
Imprime web-01, limpio y sin comillas gracias a la -r. Sin esa opción verías "web-01", y eso es lo que terminaría guardado si lo mandas a un archivo para que otro programa lo lea.
Sacar un campo de una lista
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | -r | Opción | Imprime los textos sin comillas. |
| 3 | '.usuarios[] | .email' | Valor | El filtro: los corchetes [] recorren el arreglo usuarios y la barra | encadena un filtro sobre el resultado del anterior. Dentro de las comillas, la barra no la toma la terminal. |
| 4 | datos.json | Argumento | El archivo con el arreglo. |
Una línea por usuario, con su correo. El | es el mismo pipe de la terminal, pero dentro de las comillas jq lo usa como encadenador: primero recorre el arreglo y luego a cada elemento le pide su email.
Filtrar los que cumplen una condición
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | -r | Opción | Imprime los textos sin comillas. |
| 3 | '.[] | select(.edad > 30) | .nombre' | Valor | El filtro: recorre el arreglo, select() deja pasar solo lo que cumple la condición y al final se extrae el nombre. |
| 4 | equipo.json | Argumento | El archivo con el arreglo de personas. |
Imprime solo los nombres de quienes tienen más de 30 años. select() funciona como un WHERE de SQL: deja pasar los elementos que cumplen la condición. Puedes encadenar varios: '.[] | select(.edad > 30) | select(.ciudad == "CDMX") | .nombre'.
Pasar un JSON a CSV
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | -r | Opción | Implica comillas dobles reales en vez de los caracteres escapados que JSON usaría. |
| 3 | '.[] | [.id, .nombre] | @csv' | Valor | El filtro: los corchetes [] arma un arreglo nuevo con los dos campos, y @csv lo convierte en una línea separada por comas. |
| 4 | datos.json | Argumento | El archivo de entrada. |
Cada elemento sale como una línea CSV: 1,"Ana" y 2,"Luis". Es el puente para abrir el resultado en Excel o Calc, o para cargarlo en una base de datos. Quita el -r y verás las comillas dobles escapadas, inútiles para una hoja de cálculo.
Modificar un valor y guardar el resultado
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | jq | Comando | El procesador de JSON. |
| 2 | '.puerto = 8081' | Valor | El filtro: una asignación. Busca la clave puerto y le pone 8081, dejando todo lo demás igual. |
| 3 | config.json | Argumento | El archivo de entrada, que no se modifica. |
| 4 | > | Operador | La redirección: manda la salida de jq al archivo nuevo. |
| 5 | config.nuevo.json | Argumento | El archivo donde queda el JSON ya cambiado. |
config.nuevo.json queda con puerto 8081 y todo lo demás intacto. jq nunca modifica el archivo de entrada: escribe el JSON transformado en la salida, y por eso el > va de salida. Con tee en vez de > también verías el cambio en pantalla.
Opciones
Las que sí vas a usar| Opción | Qué hace |
|---|---|
| -r--raw-output | Imprime los textos sin las comillas de JSON. Sin esto, un valor de texto sale como "web-01", con comillas. |
| -c--compact-output | Saca todo en una sola línea, sin saltos ni sangrías. Es el que se usa en scripts y para meter el JSON en la línea de otro comando. |
| -e--exit-status | Devuelve código de salida 1 cuando el filtro no arroja nada (null, false o no encuentra el campo) y 0 cuando sí. Sirve para decidir en un script sin comparar texto. |
| -n--null-input | No lee ningún archivo: usa null como valor de entrada. Junto con un filtro que arma el JSON, sirve para crear archivos desde cero. |
| -s--slurp | Lee todos los archivos de entrada y los junta en un solo arreglo, en vez de procesar cada uno por separado. |
| -S--sort-keys | Ordena las claves alfabéticamente al imprimir. Útil para comparar dos JSON y ver de un vistazo qué cambió. |
| -R--raw-input | Cada línea se lee como texto plano, sin intentar entenderla como JSON. Para trabajar con archivos que no son JSON. |
| --indent n | Cambia la sangría del formato: por omisión son dos espacios, con --indent 4 quedan cuatro y con --tab se usan tabulaciones. |
Fallas comunes
| Falla | Remedio |
|---|---|
| Olvidar la -r y guardar el valor con comillas. | jq devuelve JSON válido, así que un texto sale entre comillas. Cuando vas a usar el valor en otro comando o guardarlo en un archivo para otro programa, casi siempre necesitas -r. |
| Escribir el filtro mal y que jq se queje de sintaxis o te devuelva null. | Un objeto se abre con .clave y un arreglo con .[]; los corchetes son para índices y las llaves son para construir objetos. Si olvidas las comillas, la terminal se come los | y corta el comando por ahí, porque en ese punto el pipe ya no lo maneja jq. |
| Meterle un archivo que no es JSON y no entender el error. | jq responde parse error e incluso te dice la línea donde falló. Para trabajar con texto plano usa -R, que lee cada línea como texto sin interpretarla: jq -R -r '.' notas.txt. Y si el archivo trae texto antes del JSON, quítalo primero con tail. |
| Redirigir la salida al mismo archivo de entrada y quedarse con el JSON vacío. | jq -r '.puerto = 8081' config.json > config.json vacía el archivo antes de que jq lo lea, y el resultado es un archivo de cero bytes. Siempre a otro nombre: > config.nuevo.json. Si de verdad necesitas reemplazar el original, pásalo por sponge: jq ... config.json | sponge config.json, que viene en el paquete moreutils. |
Preguntas frecuentes
- ¿Para qué sirve jq si cat ya me muestra el archivo?
- cat te escupe el JSON crudo, tal como viene: en una sola línea o con las claves pegadas. jq lo da formateado con sangrías y, sobre todo, te deja pedir solo la parte que te interesa, como .servidor o una lista filtrada por una condición. También sirve para convertir a CSV o para editar valores antes de guardar.
- ¿Cómo saco un campo de un JSON?
- Con el filtro del punto seguido del nombre de la clave: jq -r '.servidor' config.json. Si el campo está anidado, encadena puntos o usa corchetes: .red.local.puerto. Para un arreglo, los corchetes vacíos lo recorren: .usuarios[] | .email. La -r es casi siempre obligatoria si quieres texto limpio.
- ¿Cuál es la diferencia entre jq '.a' y jq -r '.a'?
- El filtro es el mismo; cambia cómo se imprime. Sin -r, jq devuelve JSON válido: los textos salen entre comillas y con los saltos de línea escapados. Con -r imprime el valor tal cual, que es lo que quieres cuando lo usas en otro comando o en un archivo.
- ¿Cómo convierto un JSON a CSV o a una línea por registro?
- Con @csv al final del filtro: jq -r '.[] | [.id, .nombre] | @csv' datos.json. Los corchetes arman el arreglo con las columnas en el orden que quieres y @csv lo convierte en texto separado por comas. Si solo quieres un valor por línea, ya lo hace el filtro solo: jq -r '.usuarios[].email' datos.json.
- ¿Cómo creo un archivo JSON desde cero con jq?
- Con la opción -n, que le dice que no espere ninguna entrada, y un filtro con llaves: jq -n '{"nombre": "Ana", "edad": 31}' > datos.json. Las llaves construyen el objeto y las comillas impiden que la terminal las toque. También sirve para pasar variables del shell con --arg o --argjson: jq -n --arg nombre "$NOMBRE" '{nombre: $nombre}'.