json jq:如何在对象数组中按字段值过滤?

b91juud3  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(130)

有这样一个输入:

[
    {
        "foo": "aaa",
        "bar": 111
    },
    {
        "foo": "bbb",
        "bar": 111
    },
    {
        "foo": "ccc",
        "bar": 222
    },
    {
        "foo": "aaa",
        "bar": 333
    },
    {
        "foo": "ddd",
        "bar": 444
    }
]

字符串
我想选择所有的对象与“foo”键等于“bbb”或“bbb”.所以解决方案是显而易见的:
.[] | select ( .foo=="aaa" or .foo=="bbb" )https://jqplay.org/s/x7FGo1uQNW
但我想增强它,并将x=y or x=z替换为sql风格的x in (y,z)
.[] | select ( .foo in (["aaa", "bbb"]) )
导致错误:
jq:error:syntax error,unexpected IDENT,expecting ';' or ')'(Unix shell quoting issues?)at,line 1:
我也试过这个:
.[] | select ( .foo | in (["aaa", "bbb"]) )
但也不是很好
jq:error(at:21):无法检查数组是否有字符串键
这有可能吗?

rggaifut

rggaifut1#

嗯,我是用这个做到的:
第一个月
https://jqplay.org/s/g7AyRgARdU
根据这个答案:https://stackoverflow.com/a/46470951/2244766在1.5以上的版本中,有一个新的IN运算符,使生活变得更容易:

.[] | select(.foo|IN("aaa","bbb"))

字符串

4ktjp1zp

4ktjp1zp2#

SQL风格的操作符作为一种直接的选择机制对我来说并不好用;我相信它们有一个非常特定的用例,它们是唯一适合的,而对于其他任何东西,它们(充其量)都是笨拙的。至少这是我的经验。我也没有真正弄清楚这个特定的用例是什么。
在所有这些作为背景的情况下,我的建议是使用一个简单的正则表达式测试:

map(select(.foo | test("aaa|bbb")))

字符串
以JSON为例:

<~> $ jq . /tmp/so4229.json
[
  {
    "foo": "aaa",
    "bar": 111
  },
  {
    "foo": "bbb",
    "bar": 111
  },
  {
    "foo": "ccc",
    "bar": 222
  },
  {
    "foo": "aaa",
    "bar": 333
  },
  {
    "foo": "ddd",
    "bar": 444
  }
]


上述过滤将导致:

<~> $ jq 'map(select(.foo | test("aaa|bbb")))' /tmp/so4229.json
[
  {
    "foo": "aaa",
    "bar": 111
  },
  {
    "foo": "bbb",
    "bar": 111
  },
  {
    "foo": "aaa",
    "bar": 333
  }
]


如果你需要基于JSON中的其他数据生成正则表达式,你也可以这样做:

. as $data | map(select(.bar==111) | .foo) | join("|") as $regex | . = $data | map(select(.foo | test($regex)))


这将导致:

<~> $ jq '. as $data | map(select(.bar==111) | .foo) | join("|") as $regex | . = $data | map(select(.foo | test($regex)))' /tmp/so4229.json
[
  {
    "foo": "aaa",
    "bar": 111
  },
  {
    "foo": "bbb",
    "bar": 111
  },
  {
    "foo": "aaa",
    "bar": 333
  }
]


可能有一种更好的方法来运行JSON两次(一次是获取正则表达式值,一次是使用它)。

相关问题