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.
San
fuente

Respuestas:

340

Recomiendo usar la interpolación de cadenas:

jq '.users[] | "\(.first) \(.last)"'

referencia

Eric Hartford
fuente
13
esto es mucho mejor si sus datos son números
ozOli
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)'
Abrahán
fuente
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
33
jq '.users[]|.first,.last' | paste - -
optman
fuente
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)"'
machzqcq
fuente
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"
]
TinyRoy
fuente
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)

ThorSummoner
fuente
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.

Ganesh Chandrasekaran
fuente