将 json 文件转换为“键路径”,结果值位于每个“键路径”的末尾

将 json 文件转换为“键路径”,结果值位于每个“键路径”的末尾

我有一个大型且相对复杂的 json 配置文件,我想使用“grep”等简单工具来搜索键和/或值。当我“grep”时,我希望输出中的文件包含键的完整路径以及导致最终值的每个子键/数组。

这类似于在大型文件系统中搜索文件/目录,并且在找到文件/目录时能够看到文件/目录的完整路径,就像使用“find”命令一样。

另外,与我想要完成的类似比较是 xml2 实用程序,它将 xml 文件转换为键/值路径,以便于搜索和报告。

我一直在使用“jq”实用程序来使用“keys”命令解析 json 文件。我已经编写了一个粗略的 bash 脚本来沿着 json 键路径的第一个分支走下去——但找不到一种简单的方法来递归地在 json 结构的完整树上走来走去。

这是我在 bash 脚本中尝试执行的操作的手动说明。是的,它的效率非常低,但我想我会在提高性能之前让它发挥作用!

给定包含复杂配置的 file.json,我使用键来获取第一个项目,一旦有了它,我就在另一次迭代中使用它来获取下一个键,依此类推,直到到达分支的末尾...

cat file.json | jq '. | keys | .[]'
cat file.json | jq '.Blueprints | keys | .[]'
cat file.json | jq '.Blueprints.security | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor.identities | keys | .[]'

最终结果如下所示:

."Blueprints"."security"."kerberos_descriptor"."identities"[0]."keytab"."configuration"."cluster-env/smokeuser_keytab"

但当然,这只是一个非常大的键/值树的第一个分支。

答案1

jq有一些合适的内置函数可以提供帮助。您不需要太多的 Bash 技巧,而且它不太适合解决这个问题。这是 jq 中一个非常明确的版本,您应该能够根据需要进行修改:

jq -r '. as $root |
       path(..) | . as $path |
       $root | getpath($path) as $value |
       select($value | scalars) |
       ([$path[] | @json] | join(".")) + " = " + ($value | @json)
    ' < file.json

它使用变量绑定运算符... as $identifier |多次按名称记住计算值 - 其中一些是不必要的,但它们使讨论变得更容易。这些行中的每一行都将程序其余部分的变量绑定$x到左侧的值。

path/1功能是这里的关键,并且基本上已经完成了您想要的操作:path(..)生成一个包含您需要遍历以获取对象中嵌套的每个值的所有键的数组。每个路径的形式为

[ "Blueprints", "security", "kerberos_descriptor" ]

它们的使用方式与其他数组相同,也可以与解释路径的特殊函数一起使用。

path(..) | . as $path |

特别是定义一个循环:对于文件中的每个路径,调用它$path并运行程序的其余部分作为循环体。程序的其余部分是选择和输出,因此对于每个路径,都会检查它并可能生成输出行。

getpath读取这些路径数组之一并提取出它所标识的值。select让我们过滤仅选择通过测试的值 - 在这里,它仅选择符合以下条件的值标量(数字、字符串、布尔值或空值),因此中间对象和数组被忽略(空值也是如此)。

最后一行将输出格式设置为

"abc"."def".3."xyz" = true

对于文件中的每个值,每行一个,您可以根据需要进行调整。将其重定向到一个文件中,您可以grep重复浏览它。

@json正确引用值,其余部分应该很容易更改以适合您需要的格式。它不对数组使用方括号,因为手动复制join在其他情况下放入点的功能非常复杂。两边都需要括号。

相关内容