Parsen von JSON mit BusyBox-Tools

636
Josh Habdas

Ich habe ein POSIX-kompatibles Installationsskript, das die neueste Version einiger Software ermittelt, indem Informationen aus einem json blob aus einer Softwareregistrierung abgerufen werden:

meta=$(wget -qO - https://registry.npmjs.org/after-dark/latest) grep --version | grep "BSD grep" 1>/dev/null && vers=$(echo "$meta" | grep -oE '"version":(\d*?,|.*?[^\\]",)' | tr -d 'version": ,') grep --version | grep "GNU grep" 1>/dev/null && vers=$(echo "$meta" | grep -oP '"version":(\d*?,|.*?[^\\]",)' | tr -d 'version": ,') 

Ich muss diese Software mit BusyBox kompatibel machen, die wie BSD grep -Efür erweiterte Regex-Unterstützung verwendet. Es unterstützt jedoch keine --versionFlagge.

Wenn ich busybox grepstarte, sehe ich die Version von busybox. Sollte ich das nur verwenden, um Kompatibilität hinzuzufügen? Gibt es eine bessere Möglichkeit, den Codegeruch zu entfernen, ohne Abhängigkeiten zu installieren.

-1
Sie können auch generell versuchen, die Verteilung zu ermitteln, und dann die korrekte Syntax für die `grep`-Binärdatei verwenden: https://unix.stackexchange.com/questions/6345/how-can-i-get-distribution-name-und -version-number-in-a-simple-shell-script - versuchen Sie auch, absolute Pfade zu `/ bin / grep` zu verwenden. slhck vor 5 Jahren 0
IMHO haben Sie Ihre Frage bereits beantwortet - verwenden Sie `grep` von` busybox`. Es wäre auf verschiedenen Plattformen konsistent. Die einzige Sache ist, dass `busybox` nicht standardmäßig auf allen Systemen installiert ist. Ein weiterer Ansatz ist die Verwendung von "awk" für das Parsing. Es ist praktisch in allen Unix-basierten Systemen standardmäßig enthalten. Verwenden Sie nur auf kompatiblen Plattformen nur kompatible Befehle von awk, die in all ihren Geschmacksrichtungen vorhanden sind (klassisches awk, nawk, gawk ... ) wäre es viel tragbarer. Alex vor 5 Jahren 1
Danke, Alex. [Diese Antwort] (https://stackoverflow.com/a/23454288/712334) über SO liefert einige Informationen über die Hinzufügung von PCRE zu grep, die POSIX nachbuchen, und daher wird Ihr Vorschlag zur Verwendung von "awk" für eine bessere Portabilität verwendet berücksichtigt. Es scheint, dass der Grund für das Problem liegt, es kann jedoch ein Fehler oder eine undokumentierte Funktion in BSD grep sein, wenn der erweiterte reguläre Ausdruck verwendet wird, wie hier vorgeschlagen (https://stackoverflow.com/q/23454172/712334). Josh Habdas vor 5 Jahren 0

1 Antwort auf die Frage

0
Josh Habdas

Ich konnte nicht länger warten, also habe ich mir ein paar frische Augen zugelegt und die folgende Lösung gefunden, die sich mit GNU, BSD und BusyBox grep gut getestet hat und die Unterstützung für semver verbessert:

egrep -o "\"version\".*[^,]*," <<< "$meta" | cut -d ',' -f1 | cut -d ':' -f2 | tr -d '" ' 

Es ruft ERE grep mit einem Regex (mit einer Hutspitze ) auf und verwendet cutdazu, das nachfolgende Komma abzuschneiden, alles auf der rechten Seite zu packen :, die Zeichenfolge zu trimmen und alle doppelten Anführungszeichen zu entfernen.

Gegeben $metavon {"version":"5.5.0-beta4",}wird genau zurückkehren 5.5.0-beta4.
Gegeben $metavon "version" : 1,wird genau zurückkehren 1.

Angenommen, versionFeld ist nicht das letzte Feld im JSON-Blob, das aus Gründen der Lesbarkeit einen Kompromiss eingeht.

Auf die ursprüngliche Frage angewendet ergibt sich Folgendes:

vers=$(echo "$meta" | egrep -o "\"version\".*[^,]*," | cut -d ',' -f1 | cut -d ':' -f2 | tr -d '" ') 

Beseitigung der Notwendigkeit, die Version von grep zu erkennen und den Codegeruch zu entfernen.

AKTUALISIEREN:

Ich wurde schließlich zu einer eleganteren Lösung mit sedeiner Folgefrage zu SO geführt.