Fügen Sie die Bash-Variable als JSON-Schlüssel und -Wert zum Objekt hinzu

Fügen Sie die Bash-Variable als JSON-Schlüssel und -Wert zum Objekt hinzu

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, jqwar 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 .idWert 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, .iddas 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 fromdateer 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 jqFunktion 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 $daysIdleauch dies variabel ist und eine Zahl enthält:

bash$ daysIdle=3

Jetzt können wir das Echo ausgeben, $objectum jqdie 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 $objectwhich durch das, was angemessen ist. Zweitens gehe ich davon aus, dass Sie es als JSON-Zahl und nicht als Zeichenfolge möchten, die --argnormalerweise erstellt wird, also habe ich einen Filter darin, um das zu beheben. Beachten Sie zuletzt, dass ich die --argOption verwende, um jqden 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
  }
]

verwandte Informationen