假设我们有以下JSON:
[
{
"dir-1": [
"file-1.1",
"file-1.2"
]
},
"dir-1",
{
"dir-2": [
"file-2.1"
]
}
]
我们希望获得下一个输出:
"dir-1/file-1.1"
"dir-1/file-1.2"
"dir-1"
"dir-2/file-2.1"
即。获取所有叶子的路径,使用/
连接项目。有没有办法在JQ上做到这一点?
我试过这样的事情:
cat source-file | jq 'path(..) | [ .[] | tostring ] | join("/")'
但它不会产生我需要的东西。
答案 0 :(得分:3)
您可以通过将路径与其值合并来利用流的工作方式。 Streams只会为叶值发出path, value
对。只需忽略编号的索引。
$ jq --stream '
select(length == 2) | [(.[0][] | select(strings)), .[1]] | join("/")
' source-file
返回:
"dir-1/file-1.1"
"dir-1/file-1.2"
"dir-1"
"dir-2/file-2.1"
答案 1 :(得分:0)
此解决方案类似于Jeff Mercado使用tostream
和flatten
tostream | select(length==2) | .[0] |= map(strings) | flatten | join("/")
另一种方法是使用递归函数来遍历输入,例如
def slashpaths($p):
def concat($p;$k): if $p=="" then $k else "\($p)/\($k)" end;
if type=="array" then .[] | slashpaths($p)
elif type=="object" then
keys_unsorted[] as $k
| .[$k] | slashpaths(concat($p;$k))
else concat($p;.) end;
slashpaths("")
答案 2 :(得分:0)
使用--stream
很好,但以下内容可能不那么深奥:
paths(scalars) as $p
| getpath($p) as $v
| ($p | map(strings) + [$v])
| join("/")
(如果使用jq 1.4或更早版本,并且如果任何叶子可能是数字或布尔值或null,则上面的[$v]
应替换为[$v|tostring]
。)
结果是否应被视为"离开的路径"是另一回事......