使用 JQ 展平 JSON 行数组

使用 JQ 展平 JSON 行数组

我可以写

> 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 的正确方法是什么?jqnullselect(.a != null){}nulljq

答案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"

相关内容