我一直在寻找我的问题的解决方案,但没有找到一个或更好的说法,我没有用我找到的东西得到它。我的问题是:我正在 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
shell 中处理 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
,但我发现在一行上获取两个所需值的最简单方法是使用xargs
.例如:
$ jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json | xargs
25.1 40
或者,如果您想循环遍历每个.message.id
实例,我们可以添加.message.id
到输出并使用,xargs -n 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*//'
如果您只是想获取值,那么使用grep
而不是awk
or会更容易sed
:
grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"
为了提供解释,这对我来说似乎是最简单的方法。
- 它
grep -A2
会抓取您在 JSON 中查找的行以及以下两行,其中包含温度和湿度。 - 管道
grep -o
仅打印由 a 分隔的数字.
(这永远不会出现在第一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
如果您不需要打印标签,请删除