我正在尝试验证versions.json
文件中的所有版本,并获取仅包含无效版本的json作为输出。
这是一个示例文件:
{
"slamx": "16.4.0 ",
"sdbe": null,
"mimir": null,
"thoth": null,
"quasar": null,
"connectors": {
"s3": "16.0.17",
"azure": "6.0.17",
"url": "8.0.2",
"mongo": "7.0.15"
}
}
我可以使用以下jq
脚本行来完成我想做的事情:
delpaths([paths(type == "string" and contains(" ") or type == "object" | not)])
| delpaths([paths(type == "object" and (to_entries | length == 0))])
并在这样的shell上使用它:
BAD_VERSIONS=$(jq 'delpaths([paths(type == "string" and contains(" ") or type == "object" | not)]) | delpaths([paths(type == "object" and (to_entries | length == 0))])' versions.json)
if [[ $BAD_VERSIONS != "{}" ]]; then
echo >&2 $'Bad versions detected in versions.json:\n'"$BAD_VERSIONS"
exit 1
fi
并将其作为输出:
Bad versions detected in versions.json:
{
"slamx": "16.4.0 "
}
但是,这是进行过滤的一种非常复杂的方法。我需要创建一个我不想要的东西列表并将其删除,而不是只走路径树并说“保留,保留那个”,两次。
考虑到所有的路径处理内置函数和递归处理,我不禁感到必须有一种更好的方法,类似于select
,但是可以跨对象进行递归工作,但是我能做的最好的是:
. as $input |
[path(recurse(.[]?)|select(strings|contains("16")))] as $paths |
reduce $paths[] as $x ({}; . | setpath($x; ($input | getpath($x))))
我不喜欢这样做有两个原因。首先,我要创建一个新对象,而不是“编辑”旧对象。其次,它充满了变量,这指出了严重的流反转问题,并增加了复杂性。
有什么想法吗?
答案 0 :(得分:0)
对于对象,测试location.pathname.startswith....
可以缩写为to_entries|length == 0
。
如果我正确理解了目标,则可以使用length==0
,也许可以遵循以下几行:
..
如果需要路径,请考虑:
..
| objects
| with_entries(
select(( .value|type == "string" and contains(" ")) or (.value|type == "object" and length==0)) )
| select(length>0)
修改输入内容以使s3尾随空白,上面的代码将产生:
([], paths) as $p
| getpath($p)
| objects
| with_entries(
select(( .value|type == "string" and contains(" ")) or (.value|type == "object" and length==0)) )
| select(length>0) as $x
| {} | setpath($p; $x)
答案 1 :(得分:0)
感谢@jhnc's comment,我找到了解决方案。诀窍是使用流,这使嵌套变得无关紧要-我可以仅基于值应用过滤器,并且将根据键路径重新组合对象。
但是,我尝试的第一件事没有用。这个:
jq -c 'tostream|select(.[-1] | type=="string" and contains(" "))' versions.json
返回[["slamx"],"16.4.0 "]
,这就是我要搜索的内容。但是,我无法将其折回一个对象。为此,流必须具有“关闭对象”标记-仅具有一个元素的数组,该元素与要关闭的对象的最后一个键相对应。所以我将其更改为:
jq -c 'tostream|select((.[-1] | type=="string" and contains(" ")) or length==1)' versions.json
将其分解,.[-1]
选择数组的最后一个元素,将其作为值。接下来,type=="string" and contains(" ")
将选择所有值为字符串且包含空格的值。选择的最后部分length==1
保留所有“结束”标记。有趣的是,即使结束标记与最后一个键都不对应,它也可以工作,因此可能很脆弱。
完成后,我可以将其分流:
jq -c 'fromstream(tostream|select((.[-1] | type=="string" and contains(" ")) or length==1))' versions.json
jq表达式如下:
fromstream(
tostream |
select(
(
.[-1] |
type=="string" and contains(" ")
) or
length==1
)
)