一般问题
虽然我可能正在诊断事件的根本原因,确定它影响了多少用户,或者提取时间日志以评估最近代码更改对性能和吞吐量的影响,但我的工具保持不变:grep
、{2 }、sed
、tr
、uniq
、sort
、zcat
、tail
、head
、join
和 split
。为了将它们粘合在一起,Unix 为我们提供了管道,而对于更高级的过滤,我们提供了 xargs
。如果这些让我失望,总是有 perl -e
。
这些工具非常适合处理 CSV 文件、制表符分隔的文件、具有可预测行格式的日志文件或具有逗号分隔键值对的文件。换句话说,每行几乎没有上下文的文件。
XML 类似物
我最近需要浏览千兆字节的 XML 来构建用户使用情况的直方图。使用我拥有的工具这很容易,但是对于更复杂的查询,常规方法会失效。假设我有这样的文件:
<foo user="me">
<baz key="zoidberg" value="squid" />
<baz key="leela" value="cyclops" />
<baz key="fry" value="rube" />
</foo>
假设我想生成从用户到每个 <foo>
的平均 <baz>
数的映射。逐行处理不再是一种选择:我需要知道我当前正在检查哪个用户的 <foo>
,以便我知道要更新谁的平均值。完成此任务的任何类型的 Unix one 班轮都可能难以理解。
幸运的是,在 XML 领域,我们有 XPath、XQuery 和 XSLT 等出色的技术来帮助我们。
以前,我已经习惯使用出色的 XML::XPath
Perl 模块来完成上述查询,但在找到 TextMate Plugin that could run an XPath expression against my current window 后,我停止编写一次性 Perl 脚本来查询 XML。我刚刚发现 XMLStarlet 在我输入时正在安装,我期待在未来使用它。
JSON 解决方案?
所以这引出了我的问题:有没有像这样的 JSON 工具?一些调查任务需要我对 JSON 文件进行类似的查询只是时间问题,而且如果没有 XPath 和 XSLT 等工具,这样的任务将会困难得多。如果我有一堆看起来像这样的 JSON:
{
"firstName": "Bender",
"lastName": "Robot",
"age": 200,
"address": {
"streetAddress": "123",
"city": "New York",
"state": "NY",
"postalCode": "1729"
},
"phoneNumber": [
{ "type": "home", "number": "666 555-1234" },
{ "type": "fax", "number": "666 555-4567" }
]
}
并且想要找到每个人拥有的电话号码的平均数量,我可以用 XPath 做这样的事情:
fn:avg(/fn:count(phoneNumber))
问题
是否有任何命令行工具可以以这种方式“查询”JSON 文件?如果您必须在 Unix 命令行上处理一堆 JSON 文件,您使用什么工具?哎呀,是否有工作正在为 JSON 制作像这样的查询语言?如果您确实在日常工作中使用此类工具,您喜欢/不喜欢它们的哪些方面?有什么陷阱吗?
我注意到越来越多的数据序列化正在使用 JSON 完成,因此在未来分析大型数据转储时,这样的处理工具将至关重要。 JSON 的语言库非常强大,编写脚本来进行这种处理很容易,但要真正让人们玩转数据外壳工具是需要的。
相关问题
用于 XML 命令行处理的 Grep 和 Sed 等效项
JSON 是否有查询语言?
JSONPath 或其他用于 JSON/Javascript 的类似 XPath 的实用程序;或 Jquery JSON
我刚发现这个:
http://stedolan.github.com/jq/
“jq 是一个轻量级且灵活的命令行 JSON 处理器。”
2014 年更新:
@user456584 提到:
还有“json”命令(例如“jsontool”)。我倾向于喜欢它而不是 jq。非常 UNIX-y。这是该项目的链接:github.com/trentm/json –
在 http://github.com/trentm/json 的 json
自述文件中,有一长串类似内容
jq: http://stedolan.github.io/jq/ json:select: http://jsonselect.org/ jsonpipe: https://github.com/dvxhouse/jsonpipe json-command: https://github.com /zpoley/json-command JSONPath:http://goessner.net/articles/JsonPath/,http://code.google.com/p/jsonpath/wiki/Javascript jsawk:https://github.com/micha/ jsawk jshon: http://kmkeen.com/jshon/ json2: https://github.com/vi/json2 fx: https://github.com/antonmedv/fx
我创建了一个专门为命令行 JSON 操作设计的模块:
https://github.com/ddopson/underscore-cli
https://raw.github.com/ddopson/underscore-cli/master/doc/example.png
灵活 - 用于处理 JSON 数据的“瑞士军刀”工具 - 可用作简单的漂亮打印机或功能齐全的 Javascript 命令行
POWERFUL - 展示 underscore.js 的全部功能和功能(加上 underscore.string)
简单 - 使编写类似于使用“perl -pe”的 JS 单行代码变得简单
CHAINED - 可以将多个命令调用链接在一起以创建数据处理管道
多格式 - 对输入/输出格式的丰富支持 - 漂亮的打印、严格的 JSON 等 [即将推出]
DOCUMENTED - 优秀的命令行文档,每个命令都有多个示例
它使您可以非常轻松地做强大的事情:
cat earthporn.json | underscore select '.data .title'
# [ 'Fjaðrárgljúfur canyon, Iceland [OC] [683x1024]',
# 'New town, Edinburgh, Scotland [4320 x 3240]',
# 'Sunrise in Bryce Canyon, UT [1120x700] [OC]',
# ...
# 'Kariega Game Reserve, South Africa [3584x2688]',
# 'Valle de la Luna, Chile [OS] [1024x683]',
# 'Frosted trees after a snowstorm in Laax, Switzerland [OC] [1072x712]' ]
cat earthporn.json | underscore select '.data .title' | underscore count
# 25
underscore map --data '[1, 2, 3, 4]' 'value+1'
# prints: [ 2, 3, 4, 5 ]
underscore map --data '{"a": [1, 4], "b": [2, 8]}' '_.max(value)'
# [ 4, 8 ]
echo '{"foo":1, "bar":2}' | underscore map -q 'console.log("key = ", key)'
# key = foo
# key = bar
underscore pluck --data "[{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}]" name
# [ 'moe', 'larry', 'curly' ]
underscore keys --data '{name : "larry", age : 50}'
# [ 'name', 'age' ]
underscore reduce --data '[1, 2, 3, 4]' 'total+value'
# 10
它有一个非常好的命令行帮助系统并且非常灵活。它经过良好测试并可以使用;但是,我仍在构建一些功能,例如输入/输出格式的替代方案,以及在我的模板处理工具中合并(请参阅 TODO.md)。如果您有任何功能请求,请评论此帖子或在 github 中添加问题。我设计了一个相当广泛的功能集,但我很乐意优先考虑社区成员需要的功能。
您可以做的一种方法是将其转换为 XML。下面使用两个 perl 模块(JSON 和 XML::Simple)进行 fly-by 转换:
cat test.json | perl -MJSON -MXML::Simple -e 'print XMLout(decode_json(do{local$/;<>}),RootName=>"json")'
对于您的示例 json,最终结果为:
<json age="200" firstName="Bender" lastName="Robot">
<address city="New York" postalCode="1729" state="NY" streetAddress="123" />
<phoneNumber number="666 555-1234" type="home" />
<phoneNumber number="666 555-4567" type="fax" />
</json>
最近我发现 JSON 可以很容易地用 Python 编写 eval
:
$ python -c "json=eval(open('/json.txt').read()); print len(json['phoneNumber'])"
2
尽管如果 JSON 输入包含空值,该方法显然会失败。
python -c "import json;x=json.loads(open('json.txt').read());print len(x['phoneNumber'])"
还有交互式终端工具 — fx
管道到 fx 任何 JSON 和匿名函数以减少它。
$ echo '{...}' | fx [code ...]
在不传递任何参数的情况下启动交互模式:
$ curl ... | fx
https://i.stack.imgur.com/wOQSy.gif
https://github.com/antonmedv/fx
查看 FXSL 2.x library 中的 f:json-document()
。
使用这个函数可以非常容易地合并 JSON 并将其用作... XML。
例如,可以只编写以下 XPath 表达式:
f:json-document($vstrParam)/Students/*[sex = 'Female']
并使用 sex = 'Female'
获取 Students
的所有子节点
这是完整的示例:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f xs"
>
<xsl:import href="../f/func-json-document.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vstrParam" as="xs:string">
{
"teacher":{
"name":
"Mr Borat",
"age":
"35",
"Nationality":
"Kazakhstan"
},
"Class":{
"Semester":
"Summer",
"Room":
null,
"Subject":
"Politics",
"Notes":
"We're happy, you happy?"
},
"Students":
{
"Smith":
{"First Name":"Mary","sex":"Female"},
"Brown":
{"First Name":"John","sex":"Male"},
"Jackson":
{"First Name":"Jackie","sex":"Female"}
}
,
"Grades":
{
"Test":
[
{"grade":"A","points":68,"grade":"B","points":25,"grade":"C","points":15},
{"grade":"C","points":2, "grade":"B","points":29, "grade":"A","points":55},
{"grade":"C","points":2, "grade":"A","points":72, "grade":"A","points":65}
]
}
}
</xsl:variable>
<xsl:template match="/">
<xsl:sequence select=
"f:json-document($vstrParam)/Students/*[sex = 'Female']"/>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于任何 XML 文档(忽略)时,会产生正确的结果:
<Smith>
<First_Name>Mary</First_Name>
<sex>Female</sex>
</Smith>
<Jackson>
<First_Name>Jackie</First_Name>
<sex>Female</sex>
</Jackson>
f:json-document($vstrParam)/Students/*[sex = 'Female']
冗长?仅使用 f:json-document()
函数与冗长相反... :)
幸运的是,在 XML 领域,我们有 XPath、XQuery 和 XSLT 等出色的技术来帮助我们。 [...] 所以这引出了我的问题:有没有类似的 JSON 工具?
如果你问我,xidel 正是你要找的。
Xidel 是一个命令行工具,用于从 HTML/XML 页面或 JSON-API 下载和提取数据,使用 CSS、XPath 3.0、XQuery 3.0、JSONiq 或模式模板。它还可以创建新的或转换的 XML/HTML/JSON 文档。
$ xidel -s "input.json" -e '
$json/avg(
count((phoneNumber)())
)
'
2
不定期副业成功案例分享