it-swarm.com.de

Durchlaufen des JSON-Arrays im Shell-Skript

Unten finden Sie die Ausgabe des Curl-Befehls (Dateiinformationen zum Zweig). Sie benötigen ein Skript oder einen Befehl, um Dateinamen, Dateityp und Größe zu drucken.

Ich habe es mit jq versucht, konnte aber einen einzelnen Wert abrufen (jq '.values[].size')

{
  "path": {
    "components": [],
    "name": "",
    "toString": ""
  },
  "revision": "master",
  "children": {
    "size": 5,
    "limit": 500,
    "isLastPage": true,
    "values": [
      {
        "path": {
          "components": [
            ".gitignore"
          ],
          "parent": "",
          "name": ".gitignore",
          "extension": "gitignore",
          "toString": ".gitignore"
        },
        "contentId": "c9e472ef4e603480cdd85012b01bd5f4eddc86c6",
        "type": "FILE",
        "size": 224
      },
      {
        "path": {
          "components": [
            "Jenkinsfile"
          ],
          "parent": "",
          "name": "Jenkinsfile",
          "toString": "Jenkinsfile"
        },
        "contentId": "e878a88eed6b19b2eb0852c39bfd290151b865a4",
        "type": "FILE",
        "size": 1396
      },
      {
        "path": {
          "components": [
            "README.md"
          ],
          "parent": "",
          "name": "README.md",
          "extension": "md",
          "toString": "README.md"
        },
        "contentId": "05782ad495bfe11e00a77c30ea3ce17c7fa39606",
        "type": "FILE",
        "size": 237
      },
      {
        "path": {
          "components": [
            "pom.xml"
          ],
          "parent": "",
          "name": "pom.xml",
          "extension": "xml",
          "toString": "pom.xml"
        },
        "contentId": "9cd4887f8fc8c2ecc69ca08508b0f5d7b019dafd",
        "type": "FILE",
        "size": 2548
      },
      {
        "path": {
          "components": [
            "src"
          ],
          "parent": "",
          "name": "src",
          "toString": "src"
        },
        "node": "395c71003030308d1e4148b7786e9f331c269bdf",
        "type": "DIRECTORY"
      }
    ],
    "start": 0
  }
}

die erwartete Ausgabe sollte wie folgt aussehen

.gitignore    FILE     224

Jenkinsfile   FILE     1396

Für den in der Frage angegebenen Anwendungsfall ist die Antwort von @ JigglyNaga wahrscheinlich besser als diese, aber für eine kompliziertere Aufgabe können Sie die Listenelemente auch mit keys durchlaufen:

von file:

for k in $(jq '.children.values | keys | .[]' file); do
    ...
done

oder von string:

for k in $(jq '.children.values | keys | .[]' <<< "$MYJSONSTRING"); do
    ...
done

So z.B. Sie könnten verwenden:

for k in $(jq '.children.values | keys | .[]' file); do
    value=$(jq -r ".children.values[$k]" file);
    name=$(jq -r '.path.name' <<< "$value");
    type=$(jq -r '.type' <<< "$value");
    size=$(jq -r '.size' <<< "$value");
    printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'

wenn Sie keine Zeilenumbrüche für die Werte haben, können Sie dies mit einem einzelnen jq -Aufruf innerhalb der Schleife tun, wodurch es viel schneller wird:

for k in $(jq '.children.values | keys | .[]' file); do
    IFS=$'\n' read -r -d '' name type size \
        <<< "$(jq -r ".children.values[$k] | .path.name,.type,.size" file)"
    printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'
7
pLumo

Mitglieder extrahieren

jq -c '.children.values[]|[.path.components[0],.type,.size]'
  • .children.values[] Gibt jedes Mitglied des Arrays aus .values.
  • | Leitet das vorherige Ergebnis durch den nächsten Filter, ähnlich wie eine Shell-Pipe
  • [ ... , ... , ... ] Lässt alle darin enthaltenen Begriffe in einem einzigen Array erscheinen
  • Die Option -c Erzeugt ein "kompaktes" Format, d. H. ein Objekt pro Zeile

Ergebnis:

[".gitignore","FILE",224]
["Jenkinsfile","FILE",1396]
["README.md","FILE",237]
...

Formatieren des Ergebnisses

Wenn Sie eine ordentlich ausgerichtete Tabelle ausgeben möchten, ist dies eine Aufgabe, die von anderen Tools wie column oder paste besser erledigt wird.

jq -c '.children.values[]|[.path.components[0],.type,.size]' | column -t -s'[],"'
  • -t Weist column an, die Anzahl der Spalten basierend auf der Eingabe zu erraten
  • -s... Gibt die Trennzeichen an.

Ergebnis:

.gitignore   FILE       224
Jenkinsfile  FILE       1396
README.md    FILE       237

Dies hängt davon ab, dass die Zeichen [, ], , Und " Nicht in Ihren Dateinamen enthalten sind. Dies ist keine sichere Annahme.

paste kann auch mehrere Eingänge nebeneinander anordnen. Dazu können wir die JSON-Strukturen vollständig entfernen und Rohzeilen ausgeben (Hutspitze an @muru):

jq -r '.children.values[]|.path.components[0],.type,.size' | paste - - -

paste - - - Bedeutet 3 Spalten, die alle aus derselben Quelle gelesen wurden. Diesmal wird nur davon ausgegangen, dass die Dateinamen keine Zeilenumbrüche enthalten.

15
JigglyNaga

jq kann seine Ausgabe in verschiedene Formate rendern: siehe https://stedolan.github.io/jq/manual/#Formatstringsandescaping

Für tabulatorgetrennte Ausgabe:

$ jq -r '.children.values[] | [.path.name, .type, .size] | @tsv' file.json
.gitignore  FILE    224
Jenkinsfile FILE    1396
README.md   FILE    237
pom.xml FILE    2548
src DIRECTORY   
3
glenn jackman

Lösung mit ramda-cli:

% curl ... | ramda -o tsv '.children.values' 'map flat' 'map props ["path.name", "type", "size"]'
.gitignore      FILE    224
Jenkinsfile     FILE    1396
README.md       FILE    237
pom.xml FILE    2548
src     DIRECTORY

Zuerst gehen wir in die Liste der Werte und ordnen dann die Liste mit flat zu, um jeden Eintrag, der eine tiefe Objektstruktur ist, in einen flachen zu konvertieren, wobei die Schlüssel durch Punkte getrennt sind.

Anschließend können wir die Liste erneut zuordnen und die gewünschten Eigenschaften anhand ihrer Pfade auswählen, die mit Zeichenfolgen dargestellt werden.

Schließlich, -o tsv kümmert sich um die Konvertierung der resultierenden Liste von Listen in das tsv-Format.

Um zu debuggen oder besser zu verstehen, was passiert, können Sie überprüfen, was jedes Argument tut, indem Sie sie einzeln am Ende des Befehls entfernen und den Unterschied in der Ausgabe bei jedem Schritt beobachten. Es handelt sich lediglich um Operationen (oder Funktionen), die einzeln von links nach rechts auf die Daten angewendet werden.

1
raine

one-Liner-Lösung basierend auf jtc und xargs:

bash $ jtc -x'<values>l[+0]<size>l[-1]' -y'<name>l' -y'<type>l' -y'<size>l' your.json | xargs -n3
.gitignore FILE 224
Jenkinsfile FILE 1396
README.md FILE 237
pom.xml FILE 2548
bash $ 

Hinweis: Ihre Datei weist eine Unregelmäßigkeit auf (der Größenschlüssel ist nicht in jedem Datensatz vorhanden), um das erste Argument auszuschließen. -x wird auf diese Weise erstellt (verarbeitet nur die Datensätze, bei denen die Größe vorhanden ist).

1
Dmitry L.