简体   繁体   English

我如何制作此jq表达式,该表达式在jq> = 1.5中有效,向后兼容/正确于版本<1.5

[英]How do I make this jq expression, which works in jq >= 1.5, backwards-compatible / correct for versions < 1.5

In any version (that i've tried) of jq >= 1.5 , this works fine . jq >= 1.5任何版本(我尝试过)中,都可以正常工作
In any version of jq <= 1.4 , I get the following error: 在任何版本的jq <= 1.4 ,都会出现以下错误:

error: syntax error, unexpected as, expecting FORMAT or QQSTRING_START

There's a lot of information around on the error: "expecting FORMAT or QQSTRING_START" , so far what I've seen has not applied here, I wonder if it's the as that I am not implementing reliably 关于该错误,有很多信息: “ expecting FORMAT or QQSTRING_START” ,到目前为止,我所看到的并没有在这里应用,我想知道是否是as我没有可靠地实现

I can recreate the problem with this trivial code: (can be copied/pasted as is to test) 我可以使用以下普通代码来重新创建问题:(可以复制/粘贴以进行测试)

jq \
'(..|.liveBroadcastContent?'\
'| foreach . as $item (.; if $item == null then false else . end)) as $chanstatus '\
'| {location:"location",
channel:"channelid",
current_id:"vId",
id_status:$chanstatus,
url:"https://youtu.be/\("vId")"}' \
<<<'{"liveBroadcastContent":true}'

Desired result achieved on jq > 1.5 : jq > 1.5上获得所需的结果

{
  "location": "location",
  "channel": "channelid",
  "current_id": "vId",
  "id_status": true,
  "url": "https://youtu.be/vId"
}

What it's supposed to do: 它应该做什么:

  • If liveBroadcastContent exists in the input: then output it's value in the id_status key 如果liveBroadcastContent 存在 liveBroadcastContent :则将其值输出到id_status键中
  • If liveBroadcastContent does not exist : then output false in the id_status key 如果liveBroadcastContent 不存在 :则在id_status键中输出false
  • Output everything else as written 以书面形式输出其他所有内容

Actual Input : 实际输入

This is what goes into the program when there is a live stream present. 就是进入程序时, 一个现场出现的流。
This is what goes into the program when there is no live streams 就是进入程序时,有没有直播流

Hence I thought ..|.liveBroadcastContent? 因此,我以为..|.liveBroadcastContent? was the most reliable way to basically say " If this key appears somewhere in the data, please return it's value in <this> part of my fixed-format output data " 基本上是说“ 如果此键出现在数据中的某个位置 ,请在固定格式输出数据的<this>部分中返回它的值 ”是最可靠的方法。

Now that the application is obvious, please note that I am aware of using other methods such as checking the value of "totalResults" , in combination with HTTP 200 , amongst others, however: 现在该应用程序已经很明显了,请注意,我知道我将结合使用HTTP 200和其他方法使用其他方法,例如检查"totalResults"的值,但是:

  1. This application of jq may be useful elsewhere and I'd like to address it as it. jq此应用程序可能在其他地方有用,我想以此解决它。
  2. This whole program is a shared program invoked as a one-shot on demand basis, which is a backup method (API key) of a more comprehensively implemented oauth server application. 整个程序是一个共享程序,可以按需一次性调用,这是更全面实现的oauth服务器应用程序的备份方法(API密钥)。 On occasion the input data is different, thus I just want to recursively search for liveBroadcastContent 有时输入数据不同,因此我只想递归搜索liveBroadcastContent

EDIT: Just to clarify - this isn't about the behavior of jq across versions (something that would belong in the jq forums) - It's about making the most robust portable code. 编辑:只是为了澄清-这与跨版本的jq的行为无关 (属于jq论坛)-与制作最健壮的可移植代码有关。 I tend to think that versions >1.5 are simply forgiving a poorly formed expression (which I'm trying to work out here) 我倾向于认为> 1.5的版本只是宽容了格式不正确的表达式(我正在此处尝试解决)

  1. The reason your snippet fails in jq 1.4 is that foreach was only introduced in version 1.5. 您的代码段在jq 1.4中失败的原因是foreach仅在版本1.5中引入。

  2. I'm not sure that your program with foreach is consistent with your stated requirements, which unfortunately are slightly unclear. 我不确定您的带有foreach的程序是否与您声明的要求一致,但不幸的是,这些要求还不清楚。 For example, what if the "liveBroadcastContent" key appears more than once in the input JSON entity? 例如,如果“ liveBroadcastContent”键在输入JSON实体中多次出现该怎么办?

  3. Your stated requirements as I understand them (glossing over the ambiguity) would correspond to the following program, which has been tested with jq 1.4, 1.5 and the current "master" version: 据我了解,您陈述的要求(含糊不清)将与以下程序相对应,该程序已通过jq 1.4、1.5和当前的“ master”版本进行了测试:

 (reduce (..| select(type == "object" and has("liveBroadcastContent"))) as $item
    (false; $item | .liveBroadcastContent)) as $chanstatus
 | {location:"location",
    channel:"channelid",
    current_id:"vId",
    id_status:$chanstatus,
    url:"https://youtu.be/\("vId")"}
  1. For multiline programs such as this, it's usually much more convenient to use the -f option of jq, eg jq -f program.jq 对于这样的多行程序,通常使用jq的-f选项更加方便,例如jq -f program.jq

  2. If you need to accommodate jq 1.3 as well, then you'd have to handle .. , which can be done by using dotdot defined as follows: 如果还需要容纳jq 1.3,则必须处理.. ,这可以通过使用dotdot定义的dotdot来完成:

def dotdot:
  recurse(if (type | . == "object" or . == "array") then .[] else empty end);

I'm not sure what your input actually looks like, but given what you've shown here, it doesn't have to be that complicated. 我不确定您输入的内容实际上是什么样子,但是鉴于您在此处显示的内容,不必那么复杂。

{
    location: "location",
    channel: "channelid",
    current_id: "vId",
    id_status: (.liveBroadcastContent? // false),
    url: "https://youtu.be/vId"
}

You wanted to get the value of liveBroadcastContent if it exists, otherwise false and that's what precisely .liveBroadcastContent? // false 您想获取liveBroadcastContent的值(如果存在),否则为false ,这正是.liveBroadcastContent? // false .liveBroadcastContent? // false does (assuming null is not a valid value). .liveBroadcastContent? // false (假设null为无效值)。


Seeing your full input object, it seems like a search result from a web api. 看到完整的输入对象,似乎是来自Web API的搜索结果。 I don't think using recursion here is really necessary. 我认为在这里使用递归并不是真正必要的。 If the goal is take each of the results and display various information about each one, I would write this filter instead. 如果目标是获取每个结果并显示有关每个结果的各种信息,那么我将改写此过滤器。 (guessing at some of the fields) (在某些领域进行猜测)

.items[] | {
    location: .channelTitle,
    channel: .channelId,
    current_id: .id,
    id_status: (.liveBroadcastContent? // false),
    url: "https://youtu.be/\(.id)"
}

If on the other hand, you were using the search results to determine whether a feed was available (based on your negative input case), I think it would be better to approach it finding the property on the list of results, rather than just the mere existence of the property anywhere. 另一方面,如果您正在使用搜索结果来确定供稿是否可用(根据您的否定输入案例),那么我认为最好在结果列表中查找属性,而不是仅查找供稿。财产仅存在于任何地方。

I would do this instead: 我会这样做:

{
    location: "location",
    channel: "channelid",
    current_id: "vId",
    id_status: ([.items[].snippet.liveBroadcastContent | select(. != null)][0] // false),
    url: "https://youtu.be/vId"
}

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

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