首页 > 解决方案 > 在复杂对象上使用正则表达式模式获取匹配结果

问题描述

我有一个很大的 JSON 文件,我正在使用 jq 解析它。我正在使用正则表达式来提取以名为“com”的对象属性上的某个模式开头的对象。当我只做一个基本的选择并只返回它匹配的条目时,它工作得很好。我的查询看起来像:

jq .'["posts"][] | select(.com|test("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]")) | .com' jsontest.json > oops.txt

jsontest.json 看起来像:

{"posts": [{"archived_on": 3241233, "replies": 132,"com": "Life is good , and I don't want to take anything away from it . Literally #YOLO"}]}
{"posts": [{"archived_on": 456343423, "replies": 150,"com": "The premier league is returning and I am very excited for it "}]}

输出:

“生活是美好的,我不想从它身上夺走任何东西。字面意思是#YOLO”。

我想利用match(regex) 或 capture(regex)函数并获取匹配的单个输出匹配对象,在上述情况下,这将是导致正则表达式匹配的#YOLO 。

几个小时以来,我一直在偶然发现这个问题。如果有人能指导我如何实现这一目标,我将不胜感激。

标签: jsonregexmatchjq

解决方案


显示调用匹配的一种方法test是使用 idiom match(REGEX).string,以便在您的情况下您可以稍微修改您的程序以如下所示:

.["posts"][]
| select(.com|test("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]"))
| .com
| match("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]")
| .string

然而,这将返回“#Y”,而您的问题表明您想要“#YOLO”,所以看起来您会想要更像以下的东西(注意+):

.["posts"][]
| select(.com|test("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]"))
| .com
| match("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]+")
| .string

更高效的解决方案

消除对以下的调用会更有效test

.posts[].com
| match("#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]+")
| .string

使用capture

只需将 REGEX 包装在表单的命名捕获结构中(?<x>REGEX).x。例如:

.posts[].com
| capture("(?<x>#(?!(p[0-9])|([0-9])|(q[0-9]|_))[a-zA-Z0-9]+)")
| .x

推荐阅读