繁体   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

jq >= 1.5任何版本(我尝试过)中,都可以正常工作
在任何版本的jq <= 1.4 ,都会出现以下错误:

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

关于该错误,有很多信息: “ expecting FORMAT or QQSTRING_START” ,到目前为止,我所看到的并没有在这里应用,我想知道是否是as我没有可靠地实现

我可以使用以下普通代码来重新创建问题:(可以复制/粘贴以进行测试)

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}'

jq > 1.5上获得所需的结果

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

它应该做什么:

  • 如果liveBroadcastContent 存在 liveBroadcastContent :则将其值输出到id_status键中
  • 如果liveBroadcastContent 不存在 :则在id_status键中输出false
  • 以书面形式输出其他所有内容

实际输入

就是进入程序时, 一个现场出现的流。
就是进入程序时,有没有直播流

因此,我以为..|.liveBroadcastContent? 基本上是说“ 如果此键出现在数据中的某个位置 ,请在固定格式输出数据的<this>部分中返回它的值 ”是最可靠的方法。

现在该应用程序已经很明显了,请注意,我知道我将结合使用HTTP 200和其他方法使用其他方法,例如检查"totalResults"的值,但是:

  1. jq此应用程序可能在其他地方有用,我想以此解决它。
  2. 整个程序是一个共享程序,可以按需一次性调用,这是更全面实现的oauth服务器应用程序的备份方法(API密钥)。 有时输入数据不同,因此我只想递归搜索liveBroadcastContent

编辑:只是为了澄清-这与跨版本的jq的行为无关 (属于jq论坛)-与制作最健壮的可移植代码有关。 我倾向于认为> 1.5的版本只是宽容了格式不正确的表达式(我正在此处尝试解决)

  1. 您的代码段在jq 1.4中失败的原因是foreach仅在版本1.5中引入。

  2. 我不确定您的带有foreach的程序是否与您声明的要求一致,但不幸的是,这些要求还不清楚。 例如,如果“ liveBroadcastContent”键在输入JSON实体中多次出现该怎么办?

  3. 据我了解,您陈述的要求(含糊不清)将与以下程序相对应,该程序已通过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. 对于这样的多行程序,通常使用jq的-f选项更加方便,例如jq -f program.jq

  2. 如果还需要容纳jq 1.3,则必须处理.. ,这可以通过使用dotdot定义的dotdot来完成:

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

我不确定您输入的内容实际上是什么样子,但是鉴于您在此处显示的内容,不必那么复杂。

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

您想获取liveBroadcastContent的值(如果存在),否则为false ,这正是.liveBroadcastContent? // false .liveBroadcastContent? // false (假设null为无效值)。


看到完整的输入对象,似乎是来自Web API的搜索结果。 我认为在这里使用递归并不是真正必要的。 如果目标是获取每个结果并显示有关每个结果的各种信息,那么我将改写此过滤器。 (在某些领域进行猜测)

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

另一方面,如果您正在使用搜索结果来确定供稿是否可用(根据您的否定输入案例),那么我认为最好在结果列表中查找属性,而不是仅查找供稿。财产仅存在于任何地方。

我会这样做:

{
    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