私は私の問題の解決策を探していましたが、解決策が見つからなかったか、より良い表現では私が見つけた解決策を得ませんでした。私の質問は:私はRaspberry Piでスマートホームコントロールソフトウェアを使用しています。使用pilight-receive
、屋外温度センサーからデータを取り込むことができます。 pilight-receiveの出力は次のとおりです。
{
"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
}
今私の質問は、ID 1490のメッセージから温度と湿度を抽出する方法です。どのくらいの頻度で確認することをお勧めしますか? 10分ごとに実行されるcronジョブを介して出力を生成し、pilight-receive
出力データを抽出してスマートホーム制御APIにプッシュしますか?
答え1
jq
シェルを使用してjsonファイルを処理できます。
たとえば、サンプルのjsonファイルを次のように保存してから、raul.json
次のように実行しました。
$ jq .message.temperature raul.json
409.5
25.1
409.5
$ jq .message.humidity raul.json
null
40
null
ジャックほとんどのLinuxディストリビューションでは事前にパッケージ化できます。
それ自体でこれを行う方法があるかもしれませんが、jq
1行に2つの望ましい値を取得する最も簡単な方法は次のようにすることですxargs
。
$ jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json | xargs
25.1 40
.message.id
または、各インスタンスを繰り返す場合は、.message.id
出力に追加して使用できます。xargs -n 3
3つのフィールド(id、温度、湿度)があることがわかっているからです。
jq '.message.id, .message.temperature, .message.humidity' raul.json | xargs -n 3
4095 409.5 null
1490 25.1 40
2039 409.5 null
その後、awkまたは他の方法を使用してこの出力を後処理できます。
最後に、PythonとPerlの両方にjsonデータを解析して操作するための優れたライブラリがあります。 PHPやJavaを含む他の多くの言語と同様に。
答え2
私のような高度な機能についてよく知らず、プレインストールされていないawk
人のためのjq
簡単な解決策は、次のようにいくつかの基本的なコマンドを一緒にリンクすることです。
grep -A2 '"id": 1490,' stats.json | sed '/1490/d;s/"//g;s/,//;s/\s*//'
値のみを取得するには、orのgrep
代わりに使用するawk
方が簡単ですsed
。
grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"
説明すると、この方法が私にとって最も簡単な方法のようです。
grep -A2
JSONで探している行と、温度と湿度を含む次の2行を取得します。- パイプは
grep -o
区切りの数字だけを印刷します.
(最初の1490
行には表示されないため、温度と湿度という2つの値しか残りません。非常に簡単ですjq
。
答え3
コマンドラインでJSONを処理するために私が選択したツールはjqです。ただし、jqがインストールされていない場合は、Perlを使用できます。
# perl -MJSON -e '$/ = undef; my $data = <>; for my $hash (new JSON->incr_parse($data)) { my $msg = $hash->{message}; print "$msg->{temperature} $msg->{humidity}\n" if $msg->{id} == 1490 }' < data.json
25.1 40
答え4
出力は完全なJSONではなく、JSONフラグメントのセットです。出力を完全なJSONに並べ替える場合(たとえば、出力がにあると仮定file.json
):
echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]"
これにより、jtc
ツールを使用して必要なものを簡単に入手できます(次の場所で利用可能)。https://github.com/ldn-softdev/jtc):
bash $ echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]" | jtc -x "[id]:<1490>d [-1]" -y[temperature] -y[humidity] -l
"temperature": 25.1
"humidity": 40.0
bash $
上記の例で-l
ラベルを印刷する必要がない場合は、削除してください。