Verwenden von jq zum seriellen Parsen und Anzeigen mehrerer Felder in einem json


237

Ich habe diesen Json

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

Mit jq möchte ich Vor- und Nachnamen seriell anzeigen. Wie so -

Stevie Wonder
Michael Jackson

So weit bin ich gekommen -

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

Aber es wird angezeigt

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

Beachten Sie Folgendes -

  1. Die doppelten Anführungszeichen, die ich nicht will.
  2. Den Wagenrücklauf will ich nicht.
  3. Es ist durcheinander. In meiner Abfrage werden zuerst alle Vornamen und dann alle Nachnamen angezeigt. Ich möchte jedoch das vorletzte, das vorletzte Paar.

Antworten:


337

Ich empfehle die Verwendung der String-Interpolation:

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

Referenz


13
Dies ist weitaus besser, wenn Ihre Daten Zahlen sind
ozOli

203

Sie können Addition verwenden, um Zeichenfolgen zu verketten.

Zeichenfolgen werden hinzugefügt, indem sie zu einer größeren Zeichenfolge zusammengefügt werden.

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

Das obige funktioniert, wenn beide firstund lastZeichenfolge sind. Wenn Sie verschiedene Datentypen (Nummer und Zeichenfolge) extrahieren, müssen wir in äquivalente Typen konvertieren. Bezugnehmend auf die Lösung dieser Frage . Beispielsweise.

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

41
Um die JSON-Anführungszeichen zu entfernen, rufen Sie jq mit der Option -r auf, z. B. jq -r '.users [] | .first + "" + .last '
Peak

4
+1, aber für meinen Anwendungsfall versuche ich, zwei Zahlen in derselben Zeile zu formatieren. Dieser Ansatz schlägt fehl, da er keiner " "Zahl hinzugefügt werden kann . Erics Antwort liefert ein besseres Ergebnis für diesen Fall.
Synesso

9
@ Synesso: (.numA|tostring) + " " + (.numB|tostring)sollte funktionieren. Oder verwenden Sie stattdessen die Zeichenfolgeninterpolation : "\(.numA) \(.numB)".
LS

Als ich das tat jq '.users[] | .first + " " + .last', funktionierte es sehr gut, verursachte aber eine neue Linie zwischen dem Wert von .firstund .last. Ich änderte das " "an "@"und dann tat eine sed 's/@/ /g'am Ausgang „John Smith“ als Ausgabe zu erhalten. So etwas wie das:jq '.users[] | .first + "@" + .last' | sed 's/@/ /g'
Bloodysock


14

Während beide der obigen Antworten gut funktionieren, wenn Schlüssel, Wert Zeichenfolgen sind, hatte ich die Situation, eine Zeichenfolge und eine Ganzzahl anzuhängen (jq-Fehler unter Verwendung der obigen Ausdrücke)

Voraussetzung: Um eine URL unter json zu erstellen

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
}

Lösung:

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

Beachten Sie, dass das Verlassen der schließenden Klammer nicht erforderlich ist und sich irren würde.
Nymo

2
@nymo: Das entkommt nicht. \(...)ist String-Interpolation. Hier verwandelt es numerisch .ServicePortin Zeichenfolge. Anstelle der +Vorzeichen könnte eine Interpolation verwendet werden , um diese Lösung kürzer zu machen.
LS

12

Dies erzeugt eine Reihe von Namen

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

[
  "Stevie Wonder",
  "Michael Jackson"
]

4

Ich kam dem, was ich wollte, ziemlich nahe, indem ich so etwas tat

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

Die Ausgabe ist nah genug an yaml, damit ich sie normalerweise ohne große Probleme in andere Tools importieren kann. (Ich suche immer noch nach einer Möglichkeit, eine Teilmenge der Eingabe json einfach zu exportieren.)


1
Diese Art von funktioniert in meinem Fall, lassen Sie einfach die | fallen tr -d '"' am Ende und füge die Option -r zu jq hinzu.
user842479

4

Mein Ansatz wird sein (Ihr json Beispiel ist nicht gut geformt .. denke, das ist nur ein Beispiel)

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

gibt so etwas zurück

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

und grep die Ausgabe mit regulären Ausdrücken.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.