Ich habe ein JSON-Array von Objekten wie folgt.
[
{
"id" : "tmp1387816934708382026",
"owner" : "john",
"x11-display" : ":5",
"x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
},
{
"id" : "tmp4241942441012516520",
"owner" : "mike",
"x11-display" : ":10",
"x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections" : 0,
"creation-time" : "2019-05-17T16:23:05.891531Z",
"last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
}
]
Ich muss jedem Objekt, das in meinem Bash-Skript berechnet wird, einen Schlüssel mit einem Wert hinzufügen days-idle
. Das ist es, wonach ich in jedem JSON-Objekt suche.
{
"id" : "tmp1387816934708382026",
"owner" : "mike",
"x11-display" : ":5",
"x11-authority" : "/run/user/mike/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z",
"days-idle" : "$daysIdle"
}
Ich weiß, dass Sie mit einen Schlüssel hinzufügen können, jq
war mir aber nicht sicher, wie ich ein Schlüssel-Wert-Paar hinzufügen soll, bei dem der Wert eine Bash-Variable ist.
Antwort1
Angenommen, Sie möchten Ihren neuen Schlüssel dem Element mit einem bestimmten .id
Wert hinzufügen $id
:
jq --arg id "$id" --arg idle "$daysIdle" \
'( .[] | select(.id == $id)."days-idle" ) |= $idle' file
Dies wählt das Array-Element mit dem aus, .id
das wir ändern möchten, und fügt dann (eigentlich)Aktualisierung) der ."days-idle"
Schlüssel zu diesem Element mit dem bestimmten Wert, den es haben soll.
Es ."days-idle"
sollte die Zeit zwischen dem ."last-disconnection-time"
Zeitstempel undJetzt, dann können Sie alle Elemente im JSON wie folgt aktualisieren:
jq 'def dayssince: ((now - (sub("[.].*"; "Z") | fromdate))/86400) | round;
map(. += { "days-idle": (."last-disconnection-time" | dayssince) })' file
Der sub()
Aufruf kürzt den Zeitstempel am Punkt und ersetzt das Ende durch Z
. Dies liegt daran, dass fromdate
er hinsichtlich der Art der Zeitstempel, die er analysieren kann, etwas eingeschränkt ist und die Genauigkeit von unter einer Sekunde der ursprünglichen Zeitstempelzeichenfolge nicht verarbeiten kann.
Ich habe beschlossen, die eigentliche Berechnung der Anzahl der Tage seit dem Zeitstempel als jq
Funktion namens auszuführen dayssince
, nur um den Code übersichtlich zu halten.
Das resultierende JSON (bei Ausführung am 28. Juni 2021):
[
{
"id": "tmp1387816934708382026",
"owner": "john",
"x11-display": ":5",
"x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections": 1,
"creation-time": "2019-05-14T14:12:14.989287Z",
"last-disconnection-time": "2019-05-31T18:58:42.851223Z",
"days-idle": 759
},
{
"id": "tmp4241942441012516520",
"owner": "mike",
"x11-display": ":10",
"x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections": 0,
"creation-time": "2019-05-17T16:23:05.891531Z",
"last-disconnection-time": "2019-05-19T11:23:30.844797Z",
"days-idle": 771
}
]
Antwort2
Zunächst gehe ich davon aus, dass Sie das JSON-Objekt-Array in einer Bash-Variable haben, also beginnen wir damit:
bash$ object='[
{
"id" : "tmp1387816934708382026",
"owner" : "john",
"x11-display" : ":5",
"x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
},
{
"id" : "tmp4241942441012516520",
"owner" : "mike",
"x11-display" : ":10",
"x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections" : 0,
"creation-time" : "2019-05-17T16:23:05.891531Z",
"last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
}
]'
Als nächstes gehe ich davon aus, dass $daysIdle
auch dies variabel ist und eine Zahl enthält:
bash$ daysIdle=3
Jetzt können wir das Echo ausgeben, $object
um jq
die Variable hinzuzufügen.
bash$ echo "$object" | jq --arg daysIdle "$daysIdle" '.[]."days-idle" = ($daysIdle | tonumber)'
Einige wichtige Hinweise dazu. Wenn sich die Objekte tatsächlich in einer Datei befinden oder aus einem anderen Stream wie cURL stammen, ersetzen Sie einfach echo $object
which durch das, was angemessen ist. Zweitens gehe ich davon aus, dass Sie es als JSON-Zahl und nicht als Zeichenfolge möchten, die --arg
normalerweise erstellt wird, also habe ich einen Filter darin, um das zu beheben. Beachten Sie zuletzt, dass ich die --arg
Option verwende, um jq
den Wert zu übergeben. Dies ist weitaus besser und sicherer, als zu versuchen, den Wert in die JSON-Filterzeichenfolge selbst einzubetten, und verursacht darin keinen Syntaxfehler. Es wird ein Fehler ausgegeben, wenn es nicht in eine Zahl umgewandelt werden kann, aber es erlaubt keine willkürliche Einfügung in die Filterzeichenfolge. Nachdem das gesagt ist, sehen wir uns die Ausgabe an:
[
{
"id": "tmp1387816934708382026",
"owner": "john",
"x11-display": ":5",
"x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections": 1,
"creation-time": "2019-05-14T14:12:14.989287Z",
"last-disconnection-time": "2019-05-31T18:58:42.851223Z",
"days-idle": 3
},
{
"id": "tmp4241942441012516520",
"owner": "mike",
"x11-display": ":10",
"x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections": 0,
"creation-time": "2019-05-17T16:23:05.891531Z",
"last-disconnection-time": "2019-05-19T11:23:30.844797Z",
"days-idle": 3
}
]