我在SO上已经阅读了很多现有的问题,但没有一个能够解答我想要的问题。我知道使用sed / awk解析bash中的json是很困难的,但是我只需要每个记录中每个记录的键值对的每个记录都有几个键值对。我想这样做是因为它会更快,因为主JSON相当大,拥有数百万条记录。
JSON格式如下:
{
"documents":
[
{
"title":"a", //needed
"description":"b", //needed
"id":"c", //needed
....(some more:not useful)....
"conversation":
[
{
"message":"",
"id":"d", //not needed
.....(some more)....
"createDate":"e", //not needed
},
...(some more messages)....
],
"createDate":"f", //needed
....(many more labels).....
}
],
....(some more global attributes)....
}
现在为此,我需要标记为需要的属性,但是它们的公共密钥使得通过简单的sed / awk获得问题。任何人都可以建议我们是否可以使用sed / awk。如果可能的话,我们将不胜感激任何帮助。
P.S。:我知道jsawk
,但我不想引入任何依赖,所以如果可能请建议使用sed / awk。
编辑:下面给出的格式的多个重试(如文档中我们有一个列表)
"title":"a",
"description":"b"
"id":"c"
"createDate":"f"
编辑:JSON没有任何空格。它已被格式化以便于阅读。
答案 0 :(得分:5)
我建议您使用'jq'或真正的JSON解析器。您无法使用任意正则表达式“解析”JSON。你可以使用awk破解某些东西,但是如果你的输入有一个你没想到的形式,这将很容易破解。
所以,答案是,介绍一个廉价的依赖(jq,或类似的工具),并围绕它的脚本。除非您在路由器或嵌入式计算机上运行此脚本,否则您可以轻松安装jq。
答案 1 :(得分:1)
如果关键字符[
,{
,}
和]
始终在每一行中都是隔离的,那么这将有效:
#!/usr/bin/awk -f
function walk(level, end) {
while (getline > 0) {
if (level && $NF ~ end) {
return
}
if ($NF == "{") {
walk(level + 1, "},?")
} else if ($NF == "[") {
walk(level + 1, "],?")
} else if (level == 3 && match($0, /"(title|description|id|createDate)":"[^"]*"/)) {
print substr($0, RSTART, RLENGTH)
}
}
}
BEGIN {
walk(0)
exit
}
输入:
{
"documents":
[
{
"title":"a", //needed
"description":"b", //needed
"id":"c", //needed
....(some more:not useful)....
"conversation":
[
{
"message":"",
"id":"d", //not needed
.....(some more)....
"createDate":"e", //not needed
},
...(some more messages)....
],
"createDate":"f", //needed
....(many more labels).....
}
],
....(some more global attributes)....
}
输出:
"title":"a"
"description":"b"
"id":"c"
"createDate":"f"
答案 2 :(得分:0)
好吧,如果你要使用正则表达式来解析JSON,它本质上会快速,肮脏并且严重依赖于输入文件的确切语法,你可以写一些依赖于空白量的东西发生在您感兴趣的键值对之前。根据您要查找的输出类型,您可以使用以下内容:
awk '/^ {12}"title/
/^ {12}"description/
/^ {12}"id/
/^ {12}"createDate/' input_file.json
不是很好,但它可以解决您的示例输入......