Usando jq para analizar y mostrar múltiples campos en un json en serie


237

Tengo este Json

{
    "users": [
        {
            "first": "Stevie",
            "last": "Wonder"
        },
        {
            "first": "Michael",
            "last": "Jackson"
        }
    ]
}

Usando jq me gustaría mostrar el nombre y el apellido en serie. Al igual que -

Stevie Wonder
Michael Jackson

Así de lejos he llegado.

jq '.users[].first, .users[].last'

Pero muestra

"Stevie"
"Michael"
"Wonder"
"Jackson"

Observe lo siguiente:

  1. Las comillas dobles que no quiero.
  2. El retorno de carro que no quiero.
  3. Está revuelto. Mi consulta muestra primero todos los nombres y luego todos los apellidos. Sin embargo, quiero el primero, el último, el último par.

Respuestas:



203

Puede usar la suma para concatenar cadenas.

Las cadenas se agregan uniéndose en una cadena más grande.

jq '.users[] | .first + " " + .last'

Lo anterior funciona cuando ambos firsty lastson cadena. Si está extrayendo diferentes tipos de datos (número y cadena), entonces necesitamos convertir a tipos equivalentes. Refiriéndose a la solución a esta pregunta . Por ejemplo.

jq '.users[] | .first + " " + (.number|tostring)'

41
Para eliminar las comillas JSON, invoque jq con la opción -r, por ejemplo, jq ​​-r '.users [] | .first + "" + .last '
pico

44
+1, pero para mi caso de uso, estoy tratando de formatear dos números en la misma fila. Este enfoque falla porque no se puede agregar " "a un número. La respuesta de Eric da un mejor resultado para este caso.
Synesso

99
@Synesso: (.numA|tostring) + " " + (.numB|tostring)debería funcionar. O la interpolación uso de cadenas en lugar: "\(.numA) \(.numB)".
LS

Cuando lo hice jq '.users[] | .first + " " + .last', funcionó muy bien, pero causó una nueva línea entre el valor de .firsty .last. Cambié el " "a "@"y luego hice un sed 's/@/ /g'en la salida para obtener "John Smith" como salida. Algo así:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock


14

Si bien las dos respuestas anteriores funcionan bien si la clave, el valor son cadenas, tuve la situación de agregar una cadena y un entero (errores jq usando las expresiones anteriores)

Requisito: construir una url debajo de json

pradeep@seleniumframework>curl http://192.168.99.103:8500/v1/catalog/service/apache-443 | jq .[0]
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   251  100   251    0     0   155k      0 --:--:-- --:--:-- --:--:--  245k
{
  "Node": "myconsul",
  "Address": "192.168.99.103",
  "ServiceID": "4ce41e90ede4:compassionate_wozniak:443",
  "ServiceName": "apache-443",
  "ServiceTags": [],
  "ServiceAddress": "",
  "ServicePort": 1443,
  "ServiceEnableTagOverride": false,
  "CreateIndex": 45,
  "ModifyIndex": 45
}

Solución:

curl http://192.168.99.103:8500/v1/catalog/service/apache-443 |
jq '.[0] | "http://" + .Address + ":" + "\(.ServicePort)"'

tenga en cuenta que no es necesario escapar del paréntesis de cierre, y podría errar.
nymo

2
@nymo: Eso no se escapa. \(...)es la interpolación de cadenas. Aquí se convierte numérico .ServicePorten cadena. La interpolación podría usarse en lugar de los +signos para acortar esta solución.
LS

12

Esto producirá una variedad de nombres

> jq '[ .users[] | (.first + " " + .last) ]' ~/test.json

[
  "Stevie Wonder",
  "Michael Jackson"
]

4

Me acerqué bastante a lo que quería haciendo algo como esto

cat my.json | jq '.my.prefix[] | .primary_key + ":", (.sub.prefix[] | "    - " + .sub_key)' | tr -d '"' 

La salida de la cual está lo suficientemente cerca de yaml para que yo pueda importarlo a otras herramientas sin mucho problema. (Todavía estoy buscando una manera de exportar básicamente un subconjunto de la entrada json)


1
Este tipo de trabajo en mi caso, simplemente suelte el | tr -d '"' al final, y agregue la opción -r a jq.
user842479

4

mi enfoque será (su ejemplo de json no está bien formado ... supongo que es solo una muestra)

jq '.Front[] | [.Name,.Out,.In,.Groups] | join("|")'  front.json  > output.txt

devuelve algo como esto

"new.domain.com-80|8.8.8.8|192.168.2.2:80|192.168.3.29:80 192.168.3.30:80"
"new.domain.com -443|8.8.8.8|192.168.2.2:443|192.168.3.29:443 192.168.3.30:443"

y grep la salida con expresión regular.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.