如何从JSON文件提取数据


13

我有bin在寻找解决方案来解决我的问题,但找不到或更好的说我没有得到所找到的解决方案。因此,让我们谈谈我的问题是什么。我在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的方法。这取决于您对什么感到满意。蟒蛇?JavaScript?还有吗
muru

我知道一些Python和一些JavaScript,大多数我知道C ++和C#。但是在看到所有的awk和sed命令之后,我虽然必须是一些简单的命令xD
Raul Garcia Sanchez 2015年

1
与这并不难awksed提供的JSON输出保留的格式如下所示,它不需要-空格无关紧要的JSON。例如,此awk命令:awk '/temperature|humidity/ {print $2}'关闭。
muru

4
ksh93JSON解析被内置到read
mikeserv

1
检查Wheezy-backports。它可能在那里,为您节省了升级到jessie的费用(除非您打算进行任何升级)。啊哈!它被移植到喘不过气来。 packages.debian.org/wheezy-backports/jq
cas

Answers:


23

您可以用来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

jq已为大多数linux发行版预先打包。

可能有一种方法可以jq自己完成,但是我发现在一行上同时获得两个所需值的最简单方法是use 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
具体来说,jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json
glenn jackman

1
或者,bash{ read temp; read hum; } < <(jq ...)
格伦·杰克曼

1
请参阅我的答案,它仅使用grep。它可能不适用于的某些特定版本grep,但jq即使jq是专门为解析JSON而设计的,也比在这种情况下更为简单。jq无论如何,我确实给了答案一个赞。它确实是完成这项工作的工具,但有时您可以简单地用手指卸下订书钉,而不必四处寻找订书钉清除器。
rubynorails

2
除了xml或html之外,无法使用正则表达式可靠地解析json。而且大多数json数据(例如,通过网络api获取)的格式都无法通过多余的换行符和缩进来很好地格式化。为了可靠地解析json,您需要一个json解析器。 jqshell脚本就是这样的一种。其他语言具有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抓住你在JSON具有以下2行,其中包含的温度和湿度沿寻找线。
  • 用于grep -o打印的管道仅仅打印由a分隔的数字.(这将永远不会出现在第一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如果您不想打印标签,请在上面的示例中删除

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.