Mam bin szukający rozwiązania dla mojego pytania, ale nie znalazłem ani lepiej powiedział, że nie dostałem go z tym, co znalazłem. Porozmawiajmy więc o tym, o czym jest mój problem. Korzystam z oprogramowania Smart Home Control na Raspberry Pi i jak się dowiedziałem w ten weekend za pomocą pilota, mogę przechwycić dane z mojego czujnika temperatury zewnętrznej. Wyjście pilight-receive wygląda następująco:
{
"message": {
"id": 4095,
"temperature": 409.5
},
"origin": "receiver",
"protocol": "alecto_wsd17",
"uuid": "0000-b8-27-eb-0f3db7",
"repeats": 3
}
{
"message": {
"id": 1490,
"temperature": 25.1,
"humidity": 40.0,
"battery": 1
},
"origin": "receiver",
"protocol": "alecto_ws1700",
"uuid": "0000-b8-27-eb-0f3db7",
"repeats": 3
}
{
"message": {
"id": 2039,
"temperature": 409.5
},
"origin": "receiver",
"protocol": "alecto_wsd17",
"uuid": "0000-b8-27-eb-0f3db7",
"repeats": 4
}
Teraz moje pytanie do ciebie: jak do cholery mogę wyodrębnić temperaturę i wilgotność, z których identyfikator wynosi 1490. I jak poleciłbyś mi to sprawdzać często? Za pomocą zadania cron, które jest uruchamiane co 10 minut, tworzy dane wyjściowe polecenia pilight-receive, wyodrębnia dane wyjściowe i przekazuje je do interfejsu API Smart Home Control.
Ktoś ma pomysł - wielkie dzięki
źródło
awk
ised
pod warunkiem, że wyjście JSON zachowuje formatowanie pokazane tutaj, czego nie musi - białe znaki nie mają znaczenia dla JSON. Na przykład toawk
polecenie:awk '/temperature|humidity/ {print $2}'
jest zamknięte.ksh93
parsowaniem json jest wbudowany wread
.Odpowiedzi:
Możesz użyć
jq
do przetwarzania plików Json w powłoce.Na przykład zapisałem twój przykładowy plik json jako,
raul.json
a następnie uruchomiłem:jq jest dostępny w pakiecie dla większości dystrybucji Linuksa.
Prawdopodobnie jest na to sposób
jq
sam w sobie, ale najprostszym sposobem na uzyskanie obu pożądanych wartości w jednym wierszu jest użyciexargs
. Na przykład:lub, jeśli chcesz zapętlić każdą
.message.id
instancję, możemy dodać.message.id
do wyniku i użyć,xargs -n 3
ponieważ wiemy, że będą trzy pola (identyfikator, temperatura, wilgotność):Następnie możesz przetworzyć dane wyjściowe za pomocą awk lub cokolwiek innego.
Wreszcie zarówno Python, jak i Perl mają doskonałe biblioteki do analizowania i manipulowania danymi JSON. Podobnie jak kilka innych języków, w tym php i java.
źródło
jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json
{ read temp; read hum; } < <(jq ...)
grep
. Może nie działać w przypadku niektórych konkretnych wersjigrep
, ale jest prostszy niżjq
w tym scenariuszu, chociażjq
został zaprojektowany specjalnie do analizowania JSON. Zrobiłem daćjq
odebrać upvote jednak niezależnie. Jest to rzeczywiście narzędzie do pracy, ale czasami można po prostu usunąć zszywki palcami, zamiast szukać rozszywacza.jq
jest jednym z takich skryptów powłoki. inne języki mają biblioteki parsujące json.jq
jak to robi?jq
jest zdecydowanie najbardziej eleganckim rozwiązaniem. Zawk
tobą możesz pisaćźródło
Dla tych, którzy nie rozumieją zaawansowanego
awk
tak dobrze, jak chcieliby (na przykład ludzie tacy jak ja) i nie mająjq
wcześniej zainstalowanego systemu, łatwym rozwiązaniem byłoby połączenie kilku natywnych poleceń razem:Jeśli próbujesz tylko uzyskać wartości, łatwiej jest po prostu użyć
grep
zamiastawk
lubsed
:Wyjaśniając, wydaje mi się to najprostszym sposobem.
grep -A2
Chwyta linię szukasz w JSON wraz z następującymi 2 linie, które zawierają temperatury i wilgotności.grep -o
po prostu drukuje tylko cyfry oddzielone znakiem.
(co nigdy nie nastąpi w pierwszym1490
wierszu, więc pozostały Ci dwie wartości - temperatura i wilgotność. Bardzo proste.jq
Moim zdaniem nawet prostsze niż użycie .źródło
Moim wybranym narzędziem do przetwarzania JSON w wierszu poleceń jest jq. Jednak jeśli nie masz zainstalowanego jq, możesz zrobić całkiem nieźle z Perlem:
źródło
Twój wynik to zestaw fragmentów JSON, a nie pełny JSON. Jeśli / raz zmienisz układ wyjściowy na integralny JSON, np. W ten sposób (zakładając, że twój wyjściowy jest w
file.json
):wtedy łatwo jest osiągnąć to, co chcesz za pomocą
jtc
narzędzia (dostępne na stronie : https://github.com/ldn-softdev/jtc ):w powyższym przykładzie upuść,
-l
jeśli nie chcesz drukowanych etykietźródło