JSONファイルからデータを抽出する方法


13

私は私の質問の解決策を探しているビンを持っていますが、見つけたものでそれを手に入れなかった、またはより良いとは言いませんでした。私の問題が何であるかについて話しましょう。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の出力を作成し、出力のデータを抽出して、Smart Home Control Apiにプッシュします。

アイデアを持っている人-どうもありがとう


3
形式はJSONのようです。JSONを解析する方法はたくさんあります。それはあなたが何に慣れているかに依存します。Python?JavaScript?他に何か?
ムル

PythonとJavaScriptを少し知っていますが、ほとんどはC ++とC#を知っています。しかし、私はいくつかの簡単なコマンドのxDでなければならないにもかかわらず、すべてのawkを見て、コマンドをsedの後
ラウル・ガルシア・サンチェス

1
それは難しいことではありませんawkし、sedJSONの出力を提供し、ここで示された書式保持することは必要はない-空白問題ではないJSONのため。たとえば、次のawkコマンドawk '/temperature|humidity/ {print $2}'は近いです。
ムル

4
ksh93JSONの解析に組み込みされますread
mikeserv

1
wheezy-backportsを確認してください。そこにあり、jessieへのアップグレードを節約できます(とにかくアップグレードを計画していない場合)。ああ!wheezyにバックポートされています。 packages.debian.org/wheezy-backports/jq
cas

回答:


22

jqシェルでjsonファイルを処理するために使用できます。

たとえば、サンプルのjsonファイルを保存してraul.jsonから実行しました:

$ jq .message.temperature raul.json 
409.5
25.1
409.5
$ jq .message.humidity raul.json 
null
40
null

jqは、ほとんどのLinuxディストリビューション用にあらかじめパッケージ化されています。

おそらくjqそれ自体でそれを行う方法がありますが、必要な値を1行で取得するために見つけた最も簡単な方法は、を使用することxargsです。例えば:

$ jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json | xargs
25.1 40

または、各.message.idインスタンスをループする場合は.message.id、出力に追加して、xargs -n 33つのフィールド(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
具体的には、jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json
グレンジャックマン

1
または、bashで{ read temp; read hum; } < <(jq ...)
グレンジャックマン

1
単に使用する私の答えを参照してくださいgrep。の特定のバージョンでは機能しない場合がありますがgrep、JSONの解析専用に設計されjqているにもかかわらず、このシナリオよりも簡単jqです。とはjqいえ、私は答えに賛成票を投じました。それは確かに仕事のためのツールですが、場合によっては、ステープルリムーバーを探し回るのではなく、指でステープルを簡単に取り外すことができます。
ルビノレール

2
jsonは、xmlやhtmlよりも確実に正規表現で解析できません。また、ほとんどのjsonデータ(Web APIを介して取得されたデータなど)は、余分な改行とインデントで適切にフォーマットされていません。jsonを確実に解析するには、jsonパーサーが必要です。 jqシェルスクリプトのようなものです。他の言語にはjson解析ライブラリがあります。
cas

1
正規表現を使用して、あらゆるものを確実に解析できます。使用するによって異なります。どう思いますjqか?
mikeserv

0

jq断然最もエレガントなソリューションです。でawk書くことができます

awk -v id=1490 '
    $1 == "\"id\":" && $2 == id"," {matched = 1}
    $1 == "}," {matched = 0}
    matched && $1 ~ /temperature|humidity/ {sub(/,/,"", $2); print $2}
' file

0

高度で理解awkしたい人(私のような人など)がjq事前にインストールされていない人にとって、簡単な解決策は、次のようにいくつかのネイティブコマンドをパイプすることです。

grep -A2 '"id": 1490,' stats.json | sed '/1490/d;s/"//g;s/,//;s/\s*//'

値を取得しようとしているだけの場合grepは、awkまたはの代わりに使用する方が簡単ですsed

grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"

説明を提供するために、これは私にとって最も簡単な方法のようです。

  • grep -A2あなたは、温度と湿度を含んで、次の2行、一緒にJSONで探している行をつかみます。
  • grep -oaで区切られた数字のみを出力するパイプ.(最初の1490行には表示されないため、温度と湿度の2つの値が残ります。非常にシンプルですjq

0

コマンドラインで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

0

出力は、完全な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ラベルを印刷したくない場合はドロップします

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.