我试图解析从curl请求返回的JSON,就像这样:

curl 'http://twitter.com/users/username.json' |
    sed -e 's/[{}]/''/g' | 
    awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

上面将JSON划分为多个字段,例如:

% ...
"geo_enabled":false
"friends_count":245
"profile_text_color":"000000"
"status":"in_reply_to_screen_name":null
"source":"web"
"truncated":false
"text":"My status"
"favorited":false
% ...

我如何打印一个特定的字段(由-v k=文本表示)?


当前回答

这里我不能用任何答案。jq、shell数组、声明、grep -P、后视、前视、Python、Perl、Ruby甚至Bash都不可用。

剩下的答案都不太管用。JavaScript听起来很熟悉,但罐头上写的是Nescaffe——所以也不行:)即使有,对于我的简单需求——它们也会过度消耗和缓慢。

然而,对我来说,从我的调制解调器的JSON格式的回复中获得许多变量是极其重要的。我在Bourne shell (sh)做它与一个非常修剪下来的BusyBox在我的路由器!单独使用AWK没有任何问题:只需设置分隔符并读取数据。对于单个变量,这就是全部!

awk 'BEGIN { FS="\""; RS="," }; { if ($2 == "login") {print $4} }' test.json

还记得我没有数组吗?我必须在AWK解析数据中分配给我在shell脚本中需要的11个变量。我所到之处,都有人说这是不可能完成的任务。这也没有问题。

我的解决办法很简单。这段代码将:

parse .json file from the question (actually, I have borrowed a working data sample from the most upvoted answer) and picked out the quoted data, plus create shell variables from within the awk assigning free named shell variable names. eval $( curl -s 'https://api.github.com/users/lambda' | awk ' BEGIN { FS="""; RS="," }; { if ($2 == "login") { print "Login=""$4""" } if ($2 == "name") { print "Name=""$4""" } if ($2 == "updated_at") { print "Updated=""$4""" } }' ) echo "$Login, $Name, $Updated"

里面的空白没有任何问题。在我的使用中,相同的命令解析一个很长的单行输出。由于使用eval,此解决方案仅适用于可信数据。

调整它以提取未引用的数据很简单。对于大量变量,可以使用else if实现边际速度增益。缺乏数组显然意味着:没有额外的操作就没有多个记录。但是在数组可用的情况下,调整这个解决方案是一项简单的任务。

@maikel的sed回答几乎是有效的(但我不能评论它)。对于我的格式化好的数据-它工作。这里使用的例子没有太多(缺少引号)。它很复杂,很难修改。另外,我不喜欢进行11次调用来提取11个变量。为什么?我计时100循环提取9个变量:sed函数花了48.99秒,我的解决方案花了0.91秒!不公平?只提取9个变量:0.51秒vs. 0.02秒。

其他回答

在martinr和Boecko的带领下:

curl -s 'http://twitter.com/users/username.json' | python -mjson.tool

这将为您提供一个非常适合grep的输出。非常方便:

curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key

我用它从ffprobe JSON输出中提取视频时长:

MOVIE_INFO=`ffprobe "path/to/movie.mp4"  -show_streams -show_format -print_format json -v quiet`
MOVIE_SECONDS=`echo "$MOVIE_INFO"|grep -w \"duration\" |tail -1 | cut -d\" -f4 |cut -d \. -f 1`

它可以用来从任何JSON文件中提取值:

value=`echo "$jsondata" | grep -w \"key_name\" |tail -1 | cut -d\" -f4

这是一个很好的参考资料。在这种情况下:

curl 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} }  }'

有XML文件的人可能想看看我的Xidel。它是一个命令行界面,无依赖的JSONiq处理器。(也就是说,它还支持XQuery进行XML或JSON处理。)

问题中的例子是:

 xidel -e 'json("http://twitter.com/users/username.json")("name")'

或者用我自己的非标准扩展语法:

 xidel -e 'json("http://twitter.com/users/username.json").name'

基于这里的一些建议(特别是在评论中)建议使用Python,我很失望没有找到一个例子。

下面是一行程序,从JSON数据中获取单个值。它假设您将数据输送进来(从某个地方),因此在脚本上下文中应该很有用。

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hostname"]'