2017-01-31 6 views
0

Ich verwende eine Wetter-API, die alle Daten in einer einzigen Zeile ausgibt. Wie verwende ich grep, um die Werte für "Zusammenfassung" und "scheinbareTemperatur" zu erhalten? Ich beherrsche reguläre Ausdrücke grundsätzlich nicht, aber ich bin bereit zu lernen.Wie aus einer einzelnen Zeile grep

{"latitude":59.433335,"longitude":24.750486,"timezone":"Europe/Tallinn","offset":2,"currently":{"time":1485880052,"summary":"Clear","icon":"clear-night","precipIntensity":0,"precipProbability":0,"temperature":0.76,"apparentTemperature":-3.34,"dewPoint":-0.13,"humidity":0.94,"windSpeed":3.99,"windBearing":262,"visibility":9.99,"cloudCover":0.11,"pressure":1017.72,"ozone":282.98}} 

Vielen Dank!

+1

scheint wie JSON. Verwenden Sie ein JSON-fähiges Tool, keine regulären Ausdrücke. – choroba

+0

Bitte fügen Sie Ihre gewünschte Ausgabe für diese Beispieleingabe zu Ihrer Frage hinzu. – Cyrus

Antwort

2

Wie verwende ich grep, um die Werte für "Zusammenfassung" und "scheinbareTemperatur" zu erhalten?

Sie verwenden grep 's -o Flag, wodurch es nur den übereinstimmenden Teil ausgibt.

Da Sie nicht viel über Regex wissen, empfehle ich Ihnen stattdessen lernen, einen JSON-Parser zu verwenden, der für diese Aufgabe besser geeignet wäre.

Zum Beispiel mit jq würde der folgende Befehl die aktuelle Zusammenfassung extrahieren:

<whatever is your JSON source> | jq '.currently.summary' 
+0

Okay, jq funktioniert gut. Dies ist jedoch ein einfaches Bash-Skript, das ich vielleicht mit anderen teilen möchte und es wäre für sie eher unpraktisch, ein Paket herunterzuladen, nur um ein Skript auszuführen. Würde es Ihnen etwas ausmachen, mir zu zeigen, wie man es mit Regex macht? – user1901162

+0

Wenn sie nur das Skript ausführen wollen, dann denke ich, dass ein Regex tatsächlich leichter portierbar sein wird (obwohl das umstritten ist). Wenn sie in der Lage sein müssen, es aufrechtzuerhalten, egal wie sehr ich Regex liebe, würde ich 'jq' empfehlen :) edit: Ich erwähnte bereits, dass ich sowieso eine Regex-basierte Lösung hinzufügen würde, aber die von Fred sieht nett genug aus – Aaron

+0

@ user1901162 'jq's Homepage erwähnt, dass es eine portable einzelne ausführbare Datei ist (von 2.9Mo denke ich), also könnten Sie ein tar oder zip von Ihrem Skript + jq erstellen, um es zu verteilen und Anweisungen zu geben entzippe + führe das Skript aus. Außerdem müssen Sie sich nicht um die Versionskompatibilität von jq kümmern, da Sie Ihr Skript mit einer getesteten Version von jq packen. – Aaron

1

Angenommen, Ihre einzeiligen Daten werden in einer Variablen enthält genannt DATA_LINE.

Wenn Sie sicher sind, das Feld einmal in der ganzen Linie nur vorhanden ist, könnten Sie so etwas wie dies in Bash tun:

if 
    [[ "$DATA_LINE" =~ \"summary\":\"([^\"]*)\" ]] 
then 
    summary="${BASH_REMATCH[1]}" 
    echo "Summary field is : $summary" 
else 
    echo "Summary field not found" 
fi 

Sie müssten, dass einmal für jedes Feld tun, es sei denn, Sie bauen Komplexerer übereinstimmender Ausdruck, der annimmt, dass Felder in einer bestimmten Reihenfolge sind.

Als Hinweis, der passenden Ausdruck \"summary\":\"([^\"]*)\" findet das erste Vorkommen in den Daten eines Teilkette, bestehend aus:

  • "Zusammenfassung":“(Anführungszeichen eingeschlossen), gefolgt von
  • ([^ \ "] *) ein Unterausdruck, der aus einer Folge von null oder mehr Zeichen als einem doppelten Anführungszeichen besteht: Dies steht in Klammern, um es später als Element im Array BASH_REMATCH verfügbar zu machen, weil dies der Wert ist, den Sie extrahieren möchten
  • und schließlich ein letztes Zitat; Dies ist nicht unbedingt erforderlich, schützt jedoch vor dem Lesen einer abgeschnittenen Datenzeile.

Für apparentTemperature wird der Code ein bisschen anders sein, weil das Feld nicht das gleiche Format hat.

if 
    [[ "$DATA_LINE" =~ \"apparentTemperature\":([^,]*), ]] 
then 
    apparentTemperature="${BASH_REMATCH[1]}" 
    echo "Apparent temperature field is : $apparentTemperature" 
else 
    echo "Apparent temperature field not found" 
fi 
+0

Danke dafür! Aber ein bisschen Ärger. Ich kann die Zusammenfassung zeigen, aber nicht offensichtlicheTemperatur. Ich habe es zweimal für summarische und scheinbare Temperatur getan, aber letzteres funktioniert nicht. – user1901162

+0

@ user1901162 Siehe Ende der aktualisierten Antwort. Sie sollten untersuchen, wie sich die beiden Regex-Muster unterscheiden, und vergleichen, wie die Felder in Ihren Daten abgegrenzt sind, um die Änderungen zu verstehen. – Fred

+0

@ user1901162 Übrigens hat der von mir vorgeschlagene Code keine Abhängigkeit außer Bash (dieser Code ist nicht POSIX-konform). Es wird kein externer Befehl verwendet. – Fred

0

Dies ist ziemlich leicht zu verstehen, wenn Ihre Fähigkeiten begrenzt sind - wie meins! Ihren String Unter der Annahme, in einer Variablen $LINE genannt:

summary=$(sed -e 's/.*summary":"//' -e 's/".*//' <<< $LINE) 

Dann überprüfen:

echo $summary 
Clear 

, die ausgeführt wird (-e) 2 sed Befehle. Die erste ersetzt alles bis auf summary":" mit nichts und die zweite ersetzt das erste verbleibende doppelte Zitat und alles, was folgt, mit nichts.

Extract scheinbare Temperatur:

appTemp=$(sed -e 's/.*apparentTemperature"://' -e 's/,.*//' <<< $LINE) 

Dann prüfen:

echo $appTemp 
-3.34 
Verwandte Themen