为什么我无法删除jq中的这些数组项?

为什么我无法删除jq中的这些数组项?

给出命令:

echo '["tag1", "[[Super", "Duppa", "Database", "Analyst]]", "tag2"]' | jq -f ~/somefilter.jq

jq过滤器(~/somefilter.jq):

def hasOne(x): x | (startswith("[[") or endswith("]]") ); 
def looparr(r): [ r | keys[] as $i | r[$i] | select(hasOne(.)) | $i ] ; 
. as $arrray | $arrray |= .+ [ . as $arr | looparr($arr) | .[0] as $str | .[1] as $ed | $arr[$str:$ed+1] | join(" ") ] | del(.[$str:$ed+1])

为什么不del(.[$str:$ed+1])删除我刚刚连接在一起的字符串到它们自己的项目中?

相反,我收到以下错误:

jq: error: str/0 is not defined at <top-level>, line 3:
. as $arrray | $arrray |= .+ [ . as $arr | looparr($arr) | .[0] as $str | .[1] as $ed | $arr[$str:$ed+1] | join(" ") ] | del(.[$str:$ed+1])
jq: error: ed/0 is not defined at <top-level>, line 3:
. as $arrray | $arrray |= .+ [ . as $arr | looparr($arr) | .[0] as $str | .[1] as $ed | $arr[$str:$ed+1] | join(" ") ] | del(.[$str:$ed+1])

如果我| del(.[$str:$ed+1])在最后删除并将其替换为| .,我的输出将变为:

[
  "tag1",
  "[[Super",
  "Duppa",
  "Database",
  "Analyst]]",
  "tag2",
  "[[Super Duppa Database Analyst]]"
]

我想要的输出更像是:

[
  "tag1",
  "tag2",
  "[[Super Duppa Database Analyst]]"
]

当我尝试添加常量时,它工作得很好,但这并不会使我的脚本具有很强的可塑性(而且目前可能不会)。

有什么原因导致我无法访问$strand$ed吗?

答案1

我认为问题在于这些变量超出了范围,因为它们在[].我是jq新手,但以下内容重复了代码,似乎为您提供了正确的答案:

 . as $arr |
 looparr($arr) | 
 .[0] as $str |
 .[1] as $ed |
 $arr |
 del(.[$str:$ed+1])
+ [
 . as $arr |
 looparr($arr) | 
 .[0] as $str |
 .[1] as $ed |
 $arr[$str:$ed+1] |
 join(" ")
]

答案2

表达式中的问题与变量jq的范围有关$str$ed正如meuh已经提到的。它们是在数组表达式内定义的,因此作用域也在该表达式内。当您调用 时del(.[$str:$ed+1]),它们不再在范围内。

我使用下面提供了一个替代解决方案reduce,它不需要定义任何额外的函数:

reduce .[] as $item ([];
        if      isempty(.[])
        or      (last | startswith("[[") | not)
        or      (last | endswith("]]"))
        then
                # Current item is to be added to the list
                # as a separate list item.
                .       += [$item]
        else
                # Current item is to be appended to the last
                # list item (with a delimiting space).
                last    += " " + $item
        end
)

这从一个空结果数组开始。 then的隐式循环reduce迭代输入数组。输入数组的每个元素要么按原样添加到结果数组(第一个if分支),要么附加到其最后一个元素(else分支)。

如果结果数组为空或者其最后一个元素不以 开头[[或以 结尾]],则当前元素将添加到结果数组中,而不是附加到其最后一个元素。

测试:

$ jq . file
[
  "tag1",
  "[[Super",
  "Duppa",
  "Database",
  "Analyst]]",
  "tag2"
]
$ jq -f script file
[
  "tag1",
  "[[Super Duppa Database Analyst]]",
  "tag2"
]

在其中语句的| debug后面运行 with以在每个步骤后输出结果数组:endifreduce

$ jq -f script file
["DEBUG:",["tag1"]]
["DEBUG:",["tag1","[[Super"]]
["DEBUG:",["tag1","[[Super Duppa"]]
["DEBUG:",["tag1","[[Super Duppa Database"]]
["DEBUG:",["tag1","[[Super Duppa Database Analyst]]"]]
["DEBUG:",["tag1","[[Super Duppa Database Analyst]]","tag2"]]
[
  "tag1",
  "[[Super Duppa Database Analyst]]",
  "tag2"
]

相关内容