4

我在 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 来做到这一点。如果可能的话,将不胜感激任何帮助实现同样的目标。

PS:我知道jsawk但我不想引入任何依赖,所以如果可能的话,请建议使用 sed/awk。

编辑:下面给出的格式的多个 extries(如在文档中我们有一个列表)

"title":"a",
"description":"b"
"id":"c"
"createDate":"f"

编辑: JSON 没有任何空格。它的格式是为了便于阅读。

4

3 回答 3

4

我建议您使用“jq”或真正的 JSON 解析器。您不能使用任意正则表达式“解析”JSON。你可以用 awk 破解一些东西,但是如果你的输入有一个你没有预料到的形式,那将很容易破坏。

所以,答案是,引入一个廉价的依赖(jq,或类似的工具),并围绕它编写脚本。除非您在路由器或嵌入式计算机中运行此脚本,否则您很可能可以轻松安装 jq。

于 2013-09-20T04:07:22.240 回答
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"
于 2013-09-20T15:53:54.527 回答
0

好吧,如果您要使用正则表达式来解析 JSON,它本质上会快速、肮脏并且严重依赖于输入文件的确切语法,那么您可以编写一些依赖于在您感兴趣的键值对。根据您要查找的输出类型,您可以使用以下内容:

awk '/^ {12}"title/
/^ {12}"description/
/^ {12}"id/
/^ {12}"createDate/' input_file.json

不是很好,但它可以解决您的示例输入...

于 2013-09-20T04:58:13.780 回答