【发布时间】:2020-01-27 01:55:32
【问题描述】:
鉴于这三个文件...
一个带有 Statement 对象的:
{
"PolicyVersion": {
"CreateDate": "2017-07-13T18:59:21Z",
"VersionId": "v2",
"Document": {
"Version": "2012-10-17",
"Statement": {
"Action": "*",
"Resource": "*",
"Effect": "Allow"
}
},
"IsDefaultVersion": true
}
}
...还有一个带有 Statement 数组的:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
...还有一个语句嵌套在完整文档中:
{
"PolicyVersion": {
"CreateDate": "2017-07-13T18:59:21Z",
"VersionId": "v2",
"Document": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "*",
"Resource": "*",
"Effect": "Allow"
}
]
},
"IsDefaultVersion": true
}
}
当.Action == '*' 和.Resource == '*' 存在于语句中时,是否可以有一个命令来选择,无论它是一个数组,一个对象,以及它的嵌套位置?
例如,我正在扫描数千个文档,其中唯一的区别是 Statement 可能是一个对象或一个数组。
当然是这样的:jq '.PolicyVersion.Document.Statement[] | select((.Action == "*") and .Resource == "*") 适用于数组,jq '.PolicyVersion.Document.Statement | select((.Action == "*") and .Resource == "*") 适用于它不是数组但我想在一个命令中实现这一点。
我在select 周围尝试了一些方法,例如:
jq '.PolicyVersion.Document | select((.Statement[] | select((.Action == "*") and .Resource == "*") or select((.Statement[] | select((.Action == "*") and .Resource == "*")'
什么都不返回,并且:
jq '.PolicyVersion.Document | select((.Statement[] | select((.Action == "*") and .Resource == "*") or select((.Statement | select((.Action == "*") and .Resource == "*")'
返回一个 unix shell 引用错误。
【问题讨论】:
-
供您参考,可以使用 alternative unix walk-path 实用程序 jtc 来实现相同的 JSON 查询:
<file.json jtc -w'<Statement>l[Action]:<*>[-1][Resource]:<*>[^0]'。如果您愿意,我可以在单独的答案中详细说明工具的使用(PS。我是该工具的开发人员)。 -
感谢您传播知识,@Dmitry :) 始终欣赏替代方案并学习不同的方式。
-
顺便说一句,在上面的例子中,整个文档被选中(我可能误解了这个问题),在下面的答案中,我将详细说明如何只选择
Statement中包含Action的记录和Resource,如果两者都是"*"。让我知道这个问题是否意味着不同。 -
我还发现了一个使用
jmespath的 lambda 函数,它使用以下方法实现它:if jmespath.search('PolicyVersion.Document.Statement[?Effect == \'Allow\' && contains(Resource, \'*\') && contains (Action, \'*\')]', policy_version):认为我会在这里分享另一种可能的方法/解决方案。
标签: json types filtering jq jtc