![使用 JQ 展平 JSON 行数组](https://linux22.com/image/15256/%E4%BD%BF%E7%94%A8%20JQ%20%E5%B1%95%E5%B9%B3%20JSON%20%E8%A1%8C%E6%95%B0%E7%BB%84.png)
我可以写
> echo '{"a": "arbiter", "b": "brisk"}{"a": "astound", "b": "bistro"}' | jq '.a, .b'
"arbiter"
"brisk"
"astound"
"bistro"
但如果我这样做
> echo '{"a": "arbiter", "b": "brisk", "c": ["cloak", "conceal"]} {"a": "astound", "b": "bistro", "c": ["confer", "consider"]}' | jq '.a, .b, .c'
我明白了
"arbiter"
"brisk"
[
"cloak",
"conceal"
]
"astound"
"bistro"
[
"confer",
"consider"
]
我如何压平c
数组来代替
"arbiter"
"brisk"
"cloak",
"conceal"
"astound"
"bistro"
"confer",
"consider"
更新
由于空安全在几种现代语言中非常流行(并且理所当然),因此可以适当地假设上面提出的问题是不完整的。有必要知道如何处理缺少值的情况。
如果其中一个值为null
,
> echo '{"b": "brisk"}{"a": "astound", "b": "bistro"}' | jq '.a, .b'
我们在输出中得到一个空值
null
"brisk"
"astound"
"bistro"
这很可能就是我们想要的。我们可以在管道中添加第二个步骤(注意不要排除),但如果它本身排除s ,"null"
它会更干净。仅仅写作就可以解决问题,但也引入了一个层次。从内部丢弃 s 的正确方法是什么?jq
null
select(.a != null)
{}
null
jq
答案1
表达jq
方式
[.a, .b, .c]
从输入对象中提取我们想要的所有元素,并将它们放入数组中。其中一些元素可能是数组,因此我们需要展平所有元素:
[.a, .b, .c] | flatten
对于输入对象
{
"a": "arbiter",
"b": "brisk",
"c": [
"cloak",
"conceal"
]
}
这会生成数组
[
"arbiter",
"brisk",
"cloak",
"conceal"
]
你会得到一个与第二个对象相似但独立的数组。
要将这两个数组合并为一个,我们可以简单地通过 传递数据.[]
,但一种快捷的编写方式flatten | .[]
是flatten[]
。使用这个,我们得到
[.a, .b, .c] | flatten[]
概括:
echo '...as in the question...' |
jq '[.a, .b, .c] | flatten[]'
如果您还想剔除任何null
值,请通过 进行过滤select(. != null)
,或使用 提取值,或在 之前[.a//empty,.b//empty,.c//emtpy]
进行过滤。map(.//empty)
flatten[]
作为评论:您的输入 JSON 是使用echo
问题中的简单内容创建的。但是,要在命令行上正确创建 JSON,请考虑使用类似 的工具jo
,它还会对您的数据进行适当的编码以包含在 JSON 文档中:
jo
您的第二个示例 JSON 可以使用这两个调用来创建
jo a=arbiter b=brisk 'c[]'=cloak 'c[]'=conceal
jo a=astound b=bistro 'c[]'=confer 'c[]'=consider
答案2
这个答案解决了更新之前的问题。
好吧,那是相当微不足道的。不需要 Python 令人愉快的 JSON 库,甚至不需要使用 awk 或 sed 的通用性来降低这一点。写一下就足够了:
> echo '{"a": "arbiter", "b": "brisk", "c": ["cloak", "conceal"]} {"a": "astound", "b": "bistro", "c": ["confer", "consider"]}' | jq '.a, .b, .c[]'
我们得到:
"arbiter"
"brisk"
"cloak"
"conceal"
"astound"
"bistro"
"confer"
"consider"