【问题标题】:jq: select when any value is in arrayjq:当任何值在数组中时选择
【发布时间】:2019-07-04 20:27:48
【问题描述】:

给定输入 json

[
  {"title": "first line"},
  {"title": "second line"},
  {"title": "third line"}
]

我们如何才能只提取包含在第二个“过滤器”数组中列出的关键字的标题。例如在这里使用 shell 变量:

filter='["second", "third"]'

这种情况下的输出是

[
  {"title": "second line"},
  {"title": "third line"}
]

另外,如何使用数组过滤器来取反。 例如:仅返回上一个示例中的“第一行”条目。

有一个similar reply,但使用的是旧版本的 jq。 我希望当前版本的 jq 有更直观/可读的方式来做到这一点。

【问题讨论】:

    标签: json jq any set-intersection negation


    【解决方案1】:

    您可以结合使用jq 和使用数组的shell 技巧来生成过滤器。首先要生成 shell 数组,请使用 shell 中的数组表示法,如下所示。请注意,bash 数组的以下符号将在其定义中将 , 作为分隔符。现在我们需要生成一个正则表达式过滤器来匹配字符串,所以我们生成一个交替运算符

    filter=("first" "second")
    echo "$(IFS="|"; echo "${filter[*]}"
    first|second
    

    您没有提到该字符串是否仅在第一个或最后一个匹配,或者可以在.title 部分的任何位置。下面的正则表达式匹配字符串中任意位置的字符串。

    现在我们想在jq 中使用这个过滤器来匹配.title 字符串,如下所示。注意使用not 来否定结果。要提供实际匹配,请删除 |not 部分。

    jq --arg re "$(IFS="|"; echo "${filter[*]}")" '[.[] | select(.title|test($re)|not)]' < json
    

    【讨论】:

    • test()的使用是这里的关键。感谢您还添加了这种巧妙的方法来解析 shell 数组并将结果作为输入传递。
    • @Alkaline - 请注意 jq 的 test 基于正则表达式匹配,而原始问题需要关键字匹配。一般来说,与基于字符串的关键字匹配相比,天真地使用test 可以得到非常不同的结果。
    【解决方案2】:

    解决涉及“任何”一词的问题的一种方法通常是使用 jq 的any,例如使用你的 shell 变量:

    jq --argjson filter "$filter" '
      map((.title | split(" ")) as $title
          | select(any( $title[] as $t
                        | $filter[] as $kw
                        | $kw == $t )))' input.json
    

    否定

    与形式逻辑一样,您可以使用allany(与否定结合)来解决否定问题。但是不要忘记,如果你使用not, jq 的not 是一个零元过滤器。

    jq --argjson filter "$filter" '
      map((.title | split(" ")) as $title
          | select(all( $title[] as $t
                        | $filter[] as $kw
                        | $kw != $t )))' input.json
    

    其他方法

    上面使用“关键字匹配”,因为这是问题所指定的,但当然上面的 jq 表达式可以很容易地修改为使用正则表达式或其他类型的匹配。

    如果关键字列表很长,那么毫无疑问需要更好的数组交集算法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-30
      • 1970-01-01
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多