select 在数组或对象中
select within either array or object
鉴于这三个文件...
一个有语句对象:
{
"PolicyVersion": {
"CreateDate": "2017-07-13T18:59:21Z",
"VersionId": "v2",
"Document": {
"Version": "2012-10-17",
"Statement": {
"Action": "*",
"Resource": "*",
"Effect": "Allow"
}
},
"IsDefaultVersion": true
}
}
...还有一个带有语句数组:
{
"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 == '*'
时,是否可以对 select 使用单个命令,无论它是数组、对象还是嵌套位置?
例如,我正在扫描数千个文档,其中唯一的区别是 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 == "*")'
其中 returns 没有,并且:
jq '.PolicyVersion.Document | select((.Statement[] | select((.Action == "*") and .Resource == "*") or select((.Statement | select((.Action == "*") and .Resource == "*")'
其中 returns 一个 unix shell 引用错误。
以下内容可能比您需要的更通用,或者可能过于通用,所以请随意调味:
..
| objects
| select(.Statement)
| .Statement
| if type == "array" then .[] else . end
| select(.Action == "*" and .Resource == "*")
另一种针对这种特殊情况的方法:
.PolicyVersion.Document.Statement
| ..
| select(type == "object" and .Action == "*" and .Resource == "*")
在 OP 的允许下,让我在这里展示如何使用 walk-path unix 实用程序 jtc
实现相同的 JSON 查询。但是,我不会解释 walk-path,而是展示如何构建它。
我对这个问题的理解:验证 JSON 文档,这样如果文档中的任何地方都有一个带有标签 Statement
的条目,其中包含元素 "Action": "*"
和 "Resource": "*"
,然后打印包含这些元素的整个记录,否则不要打印(即留下空白输出)
1。让我们从以递归方式查找带有标签 Statement
的 JSON 条目开始(递归搜索的表示法是 <..>
,后缀 l
指示搜索 labels),因此它可以在 JSON 文档中的任何位置(我将使用第一个 JSON 示例):
bash $ <file.json jtc -w'<Statement>l'
[
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
]
bash $
2。找到 Statement
记录后,我们需要查看找到的条目 中某处是否有记录 "*"
附加 到标签 "Action"
(再次使用递归搜索,但将搜索仅限于带有 Action
标签的条目 - a.k.a。 范围搜索 ):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>'
"*"
bash $
3。现在我们需要查看找到的条目是否有兄弟 ("Resource": "*"
)。为此,让我们在 JSON 树中更上一层楼(a.k.a 地址 parent):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1]'
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
bash $
然后使用 non-recursive 范围搜索(non-recursive 搜索符号是 >..<
):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<'
"*"
bash $
4。最后,对于 select 记录,让我们再次解决最后一个 found/walked 条目的 parent:
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<[-1]'
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
bash $
上面的walk-path将方便JSON查询所有JSON文档(无论Statement
是否嵌套,或者 Action
和 Resource
记录是否(深度)记录在数组中 - 但它们必须保持兄弟姐妹)。
如果任何一个 walk lexemes 失败,那么整个输出将是空白的:
bash $ <file.json jtc -w'<Statement>l[Action]:<blah>[-1][Resource]:>*<[-1]'
bash $
最后,jtc
从文件读取时(而不是 stdin
)快几倍,出于性能原因,最好使用它传递文件作为参数:
jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<[-1]' file.json
PS> 我是 jtc
unix 实用程序的创建者,用于 JSON 处理
鉴于这三个文件...
一个有语句对象:
{
"PolicyVersion": {
"CreateDate": "2017-07-13T18:59:21Z",
"VersionId": "v2",
"Document": {
"Version": "2012-10-17",
"Statement": {
"Action": "*",
"Resource": "*",
"Effect": "Allow"
}
},
"IsDefaultVersion": true
}
}
...还有一个带有语句数组:
{
"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 == '*'
时,是否可以对 select 使用单个命令,无论它是数组、对象还是嵌套位置?
例如,我正在扫描数千个文档,其中唯一的区别是 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 == "*")'
其中 returns 没有,并且:
jq '.PolicyVersion.Document | select((.Statement[] | select((.Action == "*") and .Resource == "*") or select((.Statement | select((.Action == "*") and .Resource == "*")'
其中 returns 一个 unix shell 引用错误。
以下内容可能比您需要的更通用,或者可能过于通用,所以请随意调味:
..
| objects
| select(.Statement)
| .Statement
| if type == "array" then .[] else . end
| select(.Action == "*" and .Resource == "*")
另一种针对这种特殊情况的方法:
.PolicyVersion.Document.Statement
| ..
| select(type == "object" and .Action == "*" and .Resource == "*")
在 OP 的允许下,让我在这里展示如何使用 walk-path unix 实用程序 jtc
实现相同的 JSON 查询。但是,我不会解释 walk-path,而是展示如何构建它。
我对这个问题的理解:验证 JSON 文档,这样如果文档中的任何地方都有一个带有标签 Statement
的条目,其中包含元素 "Action": "*"
和 "Resource": "*"
,然后打印包含这些元素的整个记录,否则不要打印(即留下空白输出)
1。让我们从以递归方式查找带有标签 Statement
的 JSON 条目开始(递归搜索的表示法是 <..>
,后缀 l
指示搜索 labels),因此它可以在 JSON 文档中的任何位置(我将使用第一个 JSON 示例):
bash $ <file.json jtc -w'<Statement>l'
[
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
]
bash $
2。找到 Statement
记录后,我们需要查看找到的条目 中某处是否有记录 "*"
附加 到标签 "Action"
(再次使用递归搜索,但将搜索仅限于带有 Action
标签的条目 - a.k.a。 范围搜索 ):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>'
"*"
bash $
3。现在我们需要查看找到的条目是否有兄弟 ("Resource": "*"
)。为此,让我们在 JSON 树中更上一层楼(a.k.a 地址 parent):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1]'
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
bash $
然后使用 non-recursive 范围搜索(non-recursive 搜索符号是 >..<
):
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<'
"*"
bash $
4。最后,对于 select 记录,让我们再次解决最后一个 found/walked 条目的 parent:
bash $ <file.json jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<[-1]'
{
"Action": "*",
"Effect": "Allow",
"Resource": "*"
}
bash $
上面的walk-path将方便JSON查询所有JSON文档(无论Statement
是否嵌套,或者 Action
和 Resource
记录是否(深度)记录在数组中 - 但它们必须保持兄弟姐妹)。
如果任何一个 walk lexemes 失败,那么整个输出将是空白的:
bash $ <file.json jtc -w'<Statement>l[Action]:<blah>[-1][Resource]:>*<[-1]'
bash $
最后,jtc
从文件读取时(而不是 stdin
)快几倍,出于性能原因,最好使用它传递文件作为参数:
jtc -w'<Statement>l[Action]:<*>[-1][Resource]:>*<[-1]' file.json
PS> 我是 jtc
unix 实用程序的创建者,用于 JSON 处理