¿Cómo formatear una cadena JSON como una tabla usando jq?


Acaba de empezar con Bash scripting y se topó con jq para trabajar con JSON.

Necesito transformar una cadena JSON como la siguiente en una tabla para la salida en el terminal.

[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Jack",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]

Lo que quiero mostrar en el terminal:

ID        Name
=================
12        George
18        Jack
19        Joe

Observe cómo no quiero mostrar la propiedad de correo electrónico para cada fila, por lo que el comando jq debería incluir algún filtrado. Lo siguiente me da una lista simple de nombres e identificaciones:

list=$(echo "$data" | jq -r '.[] | .name, .id')
printf "$list"

El problema con eso es que no puedo mostrarlo como tabla. Sé que jq tiene algunas opciones de formato, pero no tan buenas como las opciones que tengo cuando uso printf. Creo que quiero obtener estos valores en una matriz que luego puedo bucle a través de mí mismo para hacer el formato...? Las cosas que probé me dan resultados variables, pero nunca lo que realmente quiero.

¿Puede alguien señalarme en la dirección correcta?

 23
Author: Micha Wiedenmann, 2016-08-25

3 answers

¿Por qué no algo como :

echo '[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Jack",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]' | jq -r '.[] | "\(.id)\t\(.name)"'

Salida

12  George
18  Jack
19  Joe

Editar 1: Para el formato de grano fino use herramientas como awk

 echo '[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Jack",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]' | jq -r '.[] | [.id, .name] | @csv' | awk -v FS="," 'BEGIN{print "ID\tName";print "============"}{printf "%s\t%s%s",$1,$2,ORS}'
ID  Name
============
12  "George"
18  "Jack"
19  "Joe"

Edit 2 : En respuesta a

No hay manera de que pueda obtener una variable que contenga una matriz recta de jq?

¿Por qué no?

Un ejemplo involucrado( de hecho modificado del suyo ) donde el correo electrónico se cambia a una matriz demuestra esto

echo '[{
    "name": "George",
    "id": 20,
    "email": [ "[email protected]" , "[email protected]" ]
}, {
    "name": "Jack",
    "id": 18,
    "email": [ "[email protected]" , "[email protected]" ]
}, {
    "name": "Joe",
    "id": 19,
    "email": [ "[email protected]" ]
}]' | jq -r '.[] | .email'

Salida

[
  "[email protected]",
  "[email protected]"
]
[
  "[email protected]",
  "[email protected]"
]
[
  "[email protected]"
]
 21
Author: sjsam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 09:06:20

Usar el filtro @tsv tiene mucho que recomendarlo, principalmente porque maneja numerosos "casos de borde"de una manera estándar:

.[] | [.id, .name] | @tsv

La adición de los encabezados se puede hacer de la siguiente manera:

jq -r '["ID","NAME"], ["--","------"], (.[] | [.id, .name]) | @tsv'

El resultado:

ID  NAME
--  ------
12  George
18  Jack
19  Joe
 32
Author: peak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 11:50:23

Si los valores no contienen espacios, esto podría ser útil:

read -r -a data <<<'name1 value1 name2 value2'

echo "name value"
echo "=========="

for ((i=0; i<${#data[@]}; i+=2)); do
  echo ${data[$i]} ${data[$((i+1))]}
done

Salida

name value
==========
name1 value1
name2 value2
 0
Author: Micha Wiedenmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 11:54:37