检查关键字的子字符串是否存在于数组中。

huangapple go评论62阅读模式
英文:

JQ: check if substring from key exists in an array

问题

我有一个包含对象的数组作为输入,每个对象如下所示:

{
  "downloadDir": "/merge/downloads",
  "id": 2485,
  "labels": [
    "irrelevant",
    "downloads"
  ]
}

我试图让 JQ 遍历每个对象并找出那些在.labels数组中没有一个元素是.downloadDir第一个和第二个'/'之间的子字符串的对象,即

  • 对于"/merge/downloads",应该是"downloads"
  • 对于"/merge/tv/downloads",应该是"tv"
  • 对于"/merge/tv-share/downloads",应该是"tv-share"

对于匹配的对象,它应该返回它们的.id。

经过查看Stack Overflow上的一些类似问题,我认为逻辑应该是这样的:map(select(.labels | index(.downloadDir)))。如果我在index()中有一个静态字符串,比如map(select(.labels | index("downloads"))),这个方法有效,但我无法使其与.downloadDir一起工作:它会抛出"Cannot index array with string "downloadDir""或"Cannot index string with string "labels"",这取决于我是否将输入传递为数组。

我完全不知道如何处理将正则表达式应用于.downloadDir以获取所需的子字符串。

英文:

I have an array of objects as input, each object looking as follows:

{
  "downloadDir": "/merge/downloads",
  "id": 2485,
  "labels": [
    "irrelevant",
    "downloads"
  ]
}

I am trying to have JQ go through every object and find those, which do not have an element in the .labels array that is a substring of .downloadDir between 1st and 2nd '/', i.e.

  • for "/merge/downloads" it should be "downloads"
  • for "/merge/tv/downloads" it should be "tv"
  • for "/merge/tv-share/downloads" it should be "tv-share"

For matching objects it should return their .id.

Having reviewed some similar questions on Stack Overflow, I'm thinking the logic is supposed to look something like this: map(select(.labels | index(.downloadDir))). This works if I have a static string in index(), like map(select(.labels | index("downloads"))), however I can't get it to work with .downloadDir: it throws out "Cannot index array with string "downloadDir"" or "Cannot index string with string "labels"", depending on whether I pass the input as an array or not.

I am entirely unsure how to approach applying a regex to .downloadDir to grab the needed substring from it.

答案1

得分: 0

我在输入中添加了一个对象进行测试:

[{
  "downloadDir": "/merge/downloads",
  "id": 2485,
  "labels": [
    "irrelevant",
    "downloads"
  ]
},{
  "downloadDir": "/merge/tv/downloads",
  "id": 2486,
  "labels": [
    "irrelevant",
    "downloads"
  ]
}]

以下表达式返回了第一个对象的id,而不是第二个:

<file.json jq '.[]
               | (.downloadDir | split("/")\[2\]) as $key
               | select(.labels | map(. != $key) | all).id'
英文:

I added one more object into the input for testing:

[{
  &quot;downloadDir&quot;: &quot;/merge/downloads&quot;,
  &quot;id&quot;: 2485,
  &quot;labels&quot;: [
    &quot;irrelevant&quot;,
    &quot;downloads&quot;
  ]
},{
  &quot;downloadDir&quot;: &quot;/merge/tv/downloads&quot;,
  &quot;id&quot;: 2486,
  &quot;labels&quot;: [
    &quot;irrelevant&quot;,
    &quot;downloads&quot;
  ]
}]

The following expression returned the id of the first object, not the second:

&lt;file.json jq &#39;.[]
               | (.downloadDir | split(&quot;/&quot;)[2]) as $key
               | select(.labels | map(. != $key) | all).id&#39;

答案2

得分: 0

jq 'select(any(.labels[] == (.downloadDir / "/")[2]; .)).id' input.json
2485

演示

这适用于一系列项目的流(与您的示例建议的一样)。如果您的输入确实是一组项目,请在前面加上 .[]

英文:

Split the .downloadDir at &quot;/&quot; using /, and take the second item. Compare it to each item in .labels and yield true if at least one (any) matches. select those items, and output the .id.

jq &#39;select(any(.labels[] == (.downloadDir / &quot;/&quot;)[2]; .)).id &#39; input.json
2485

Demo

This works on a stream of items (as suggested by your sample). If your input is indeed an array of items, prepend .[].

huangapple
  • 本文由 发表于 2023年4月6日 21:08:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75949905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定