使用 sed 命令的正则表达式来解析 json 文本

使用 sed 命令的正则表达式来解析 json 文本

我有这个 json 文本:

{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

我想提取 buildStatus 的总体状态,即预期输出为“ERROR”

"buildStatus" : {
    "status" : "ERROR",
    ....
}

我尝试了下面的 sed 表达式,但它不起作用,它返回OK

status= sed -E 's/.*\"buildStatus\":.*\"status\":\"([^\"]*)\",.*/\1/' jsonfile

我究竟做错了什么?

答案1

不要使用正则表达式解析复杂的嵌套数据结构(如 JSON 或 XML),而要使用适当的 JSON 解析器,如jshon

首先你需要安装它:

sudo apt-get install jshon

然后,您必须通过标准输入向其提供 JSON 数据以进行解析,这样您就可以使用管道 ( |) 将另一个命令的输出重定向到那里或将文件重定向到它 ( < filename)。

提取所需数据所需的参数如下所示:

jshon -e "buildStatus" -e "status" -u
  • -e "buildStatus"从顶级字典中选择具有“buildStatus”索引的元素。
  • -e "status"从上面选择的第二级字典中选择具有“状态”索引的元素。
  • -u将选定的数据从 JSON 转换为纯数据(即,这里删除了字符串周围的引号)

因此,您运行的命令(取决于您从哪里获取数据)看起来像下列命令之一:

jshon -e "buildStatus" -e "status" -u < YOUR_INPUT_FILE
YOUR_JSON_PRODUCING_COMMAND | jshon -e "buildStatus" -e "status" -u

要了解更多信息jshon,您可以阅读其在线手册页这里或者直接输入man jshon

答案2

工作职位jq

jq -r '.["buildStatus"]["status"]' file.json

可以缩写为:

jq -r '.buildStatus.status' file.json

-r( ) 输出不带字符串格式的--raw-output字符串,即不带引号的字符串。json

例子:

% cat file.json                   
{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

% jq -r '.["buildStatus"]["status"]' file.json
ERROR

% jq -r '.buildStatus.status' file.json       
ERROR

如果尚未安装,请通过以下方式安装(可在 Universe 存储库中找到):

sudo apt-get install jq 

答案3

如上所述,使用适当的 API 解析复杂的结构化数据是更好的选择。Python 有json一个模块,我个人在我的脚本中经常使用它,并且可以很容易地提取所需的字段,如下所示:

$ python -c 'import sys,json;print json.load(sys.stdin)["buildStatus"]["status"]' <  input.txt
ERROR

这里发生的事情是,我们将输入文件重定向到 Python 的标准输入,并使用 读取该文件json.load()。这将成为具有键“buildStatus”的 Python 字典,并且它包含另一个具有“status”键的 Python 字典。因此,我们只是打印出存储在另一个字典中的字典中键的值。相当简单。

除了简单之外,另一个优点是 python 和这个 API 都是预装的,并默认随 Ubuntu 一起提供。

答案4

不是说你应该使用sed(我认为有人因为我没有写强制性警告而对我投了反对票),但如果你需要在下一个行到,buildStatus因为你似乎在尝试自己的尝试,你需要告诉使用命令sed读取下一行N

$ sed -rn '/buildStatus/N;s/.*buildStatus.*\n.*: "(.*)",/\1/p' file
ERROR

笔记:

  • -n在我们要求之前不要打印任何内容
  • -r使用 ERE (与 相同-E)
  • /buildStatus/N找到这个模式并阅读下一行
  • s/old/new/old用。。。来代替new
  • .*行中任意数量的任意字符
  • \n新队
  • : "(.*)",: "保存在和之间出现的任何字符",
  • \1返回引用已保存的模式
  • p打印我们工作的部分

相关内容