Utilizzo di jq per analizzare e visualizzare più campi in un json in serie


237

Ho questo Json

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

Usando jq vorrei visualizzare il nome e il cognome in serie. Così -

Stevie Wonder
Michael Jackson

Questo è quanto sono arrivato lontano -

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

Ma viene visualizzato

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

Si noti quanto segue:

  1. Le doppie virgolette che non voglio.
  2. La carrozza ritorna che non voglio.
  3. È confuso. La mia query visualizza prima tutti i nomi, quindi tutti i cognomi. Tuttavia, voglio il primo, l'ultimo, l'ultimo paio.

Risposte:


339

Consiglio di usare l'interpolazione di stringhe:

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

riferimento


13
questo è molto meglio se i tuoi dati sono numeri
ozOli

203

È possibile utilizzare l' aggiunta per concatenare le stringhe.

Le stringhe vengono aggiunte unendo in una stringa più grande.

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

Quanto sopra funziona quando entrambi firste lastsono stringa. Se stai estraendo tipi di dati diversi (numero e stringa), allora dobbiamo convertire in tipi equivalenti. Riferendosi alla soluzione su questa domanda . Per esempio.

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

41
Per eliminare le virgolette JSON, invocare jq con l'opzione -r, ad esempio jq -r '.users [] | .first + "" + .last '
picco

4
+1, ma per il mio caso d'uso, sto cercando di formattare due numeri sulla stessa riga. Questo approccio non riesce perché non può essere aggiunto " "a un numero. La risposta di Eric dà un risultato migliore per questo caso.
Synesso,

9
@Synesso: (.numA|tostring) + " " + (.numB|tostring)dovrebbe funzionare. O l'uso di interpolazione di stringhe invece: "\(.numA) \(.numB)".
LS

Quando l'ho fatto jq '.users[] | .first + " " + .last', ha funzionato molto bene, ma ha causato una nuova linea tra il valore di .firste .last. Ho cambiato il " "to "@"e poi ho fatto un sed 's/@/ /g'output per ottenere "John Smith" come output. Qualcosa del genere:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock,


14

Mentre entrambe le risposte sopra funzionano bene se chiave, valore sono stringhe, ho avuto una situazione per aggiungere una stringa e un numero intero (errori jq usando le espressioni sopra)

Requisito: costruire un url sotto 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
}

Soluzione:

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

si noti che sfuggire alla parentesi di chiusura non è necessario e sarebbe errato.
nymo,

2
@nymo: non sta scappando. \(...)è l'interpolazione di stringhe. Qui trasforma il valore numerico .ServicePortin stringa. L'interpolazione potrebbe essere utilizzata al posto dei +segni per rendere più breve questa soluzione.
LS

12

Questo produrrà una matrice di nomi

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

[
  "Stevie Wonder",
  "Michael Jackson"
]

4

Mi sono avvicinato molto a quello che volevo facendo qualcosa del genere

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

Il mio output è abbastanza vicino da poterlo importare di solito in altri strumenti senza troppi problemi. (Sto ancora cercando un modo per esportare di base un sottoinsieme dell'input json)


1
Questo tipo di lavori nel mio caso, basta rilasciare il | tr -d '"' alla fine e aggiungi l'opzione -r a jq.
user842479

4

il mio approccio sarà (il tuo esempio JSON non è ben formato .. immagino che sia solo un esempio)

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

restituisce qualcosa del genere

"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"

e grep l'output con espressione regolare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.