简体   繁体   English

jq如何按列表中的字段值过滤

[英]jq how to filter by field value in list

having an input like this:有这样的输入:

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

i would like to select all objects with "foo" key equal to "aaa" or "bbb".我想 select 所有“foo”键等于“aaa”或“bbb”的对象。 so the solution is obvious:所以解决方案很明显:

.[] | select (.foo=="aaa" or.foo=="bbb" ) .[] | select (.foo=="aaa" or.foo=="bbb" ) ( https://jqplay.org/s/x7FGo1uQNW ) .[] | select (.foo=="aaa" or.foo=="bbb" ) ( https://jqplay.org/s/x7FGo1uQNW )

but i would like to enhance it and replace that x=y or x=z to sql'ish styled x in (y,z) .但我想增强它并将x=y or x=z替换为 sql'ish styled x in (y,z) and i got stuck, as the natural try:我被卡住了,作为自然的尝试:

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

results in an error:导致错误:

jq: error: syntax error, unexpected IDENT, expecting ';' jq: 错误:语法错误,意外 IDENT,期待 ';' or ')' (Unix shell quoting issues?) at, line 1:或 ')' (Unix shell 引用问题?)在第 1 行:

i also tried this:我也试过这个:

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

but also not great...但也不是很好...

jq: error (at:21): Cannot check whether array has a string key jq:错误(at:21):无法检查数组是否有字符串键

is this even posible?这甚至可能吗?

hmm, i managed to do it with this:嗯,我设法做到了这一点:

.[] | select(.foo as $tmpvar | ["aaa", "bbb"] | index ($tmpvar ) )

https://jqplay.org/s/g7AyRgARdU https://jqplay.org/s/g7AyRgARdU

According to this answer: https://stackoverflow.com/a/46470951/2244766 in versions above 1.5 there is a new IN operator that makes life a bit easier:根据这个答案: https://stackoverflow.com/a/46470951/2244766在 1.5 以上的版本中,有一个新的IN运算符可以让生活更轻松:

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

The SQL-style operators don't work well for me as a straight-forward selection mechanism; SQL 风格的运算符不适合我作为一种直接的选择机制。 I believe they have a very specific use-case, for which they are uniquely suitable for, and for anything else they're (at best) clunky.我相信它们有一个非常具体的用例,它们是独一无二的,而对于其他任何东西来说,它们(充其量)是笨重的。 At least that's been my experience.至少这是我的经验。 And I haven't really figured out what that specific use-case is, either.而且我还没有真正弄清楚那个特定的用例是什么。

With all of that as a backdrop, my recommendation is to use a simple regex test:以所有这些为背景,我的建议是使用简单的正则表达式测试:

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

Given the example JSON:给定示例 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
  }
]

the above filter would result in:上述过滤器将导致:

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

If you need to generate the regex based on other data within the JSON, you can do that, too:如果您需要根据 JSON 中的其他数据生成正则表达式,您也可以这样做:

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

which would result in:这将导致:

<~> $ 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
  }
]

There may be a better way to run through the JSON twice (once to get the regex values, once to use it).可能有更好的方法来运行 JSON 两次(一次获取正则表达式值,一次使用它)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM