将多个对象传递给jq以进行递归过滤操作

时间:2015-11-11 17:27:04

标签: jq

我正在尝试使用jq 1.5开发一个脚本,该脚本可以接受一个或多个表示密钥的用户输入,并以递归方式从JSON输入中删除它们。

我引用的JSON在这里: https://github.com/EmersonElectricCo/fsf/blob/master/docs/Test.json

我的脚本看起来效果很好,如下所示。

def post_recurse(f):
   def r:
      (f | select(. != null) | r), .;
      r;
def post_recurse:
   post_recurse(.[]?);
(post_recurse | objects) |= del(.META_BASIC_INFO)

但是,我想用一个或多个用户输入替换META_BASIC_INFO。我将如何实现这一目标?我从命令行开始使用--arg,但我不知道如何将它合并到我的.jq脚本中?

我已尝试将del(.META_BASIC_INFO)替换为del(.$module)并使用cat test.json | ./jq -f fsf_key_filter.jq --arg module META_BASIC_INFO进行调试以进行测试,但这不起作用。

非常感谢任何有关此事的指导!

解答:

基于一些建议,我能够达到以下工作和用户JQ。

Innvocation:

cat test.json | jq --argjson delete '["META_BASIC_INFO","SCAN_YARA"]' -f fsf_module_filter.jq

代码:

def post_recurse(f):
        def r:
                (f | select(. != null) | r), .;
                r;
def post_recurse:
        post_recurse(.[]?);
(post_recurse | objects) |= reduce $delete[] as $d (.; delpaths([[ $d ]]))

3 个答案:

答案 0 :(得分:1)

似乎名称module是1.5中的关键字,因此$module会导致语法错误。您应该使用其他名称。还有其他内置函数可以为你做递归,考虑使用它们而不是自己生成。

$ jq '(.. | objects | select(has($a))) |= del(.[$a])' --arg a "META_BASIC_INFO" Test.json

答案 1 :(得分:0)

您也可以使用delpaths / 1。例如:

$ jq -n '{"a":1, "b": 1} | delpaths([["a"]])'
{
  "b": 1
}

也就是说,修改你的程序,使最后一行如下所示:

(post_recurse | objects) |= delpaths([[ $delete ]] )

你会像这样调用jq:

$ jq --arg delete "META_BASIC_INFO" -f delete.jq input.json

(不能使用--arg module ...作为" $ module"具有某种保留状态。)

答案 2 :(得分:0)

这是一个"一行"解决方案使用walk / 1:

jq --arg d "META_BASIC_INFO" 'walk(if type == "object" then del(.[$d]) else . end)' input.json

如果你的jq中没有walk / 1,那么这就是它的定义:

# Apply f to composite entities recursively, and to atoms
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
    elif type == "array" then map( walk(f) ) | f
    else f
    end;

如果你想递归删除一堆键值对,那么这是一种使用--argjson的方法:

rdelete.jq:

def rdelete(key):
  walk(if type == "object" then del(.[key]) else . end);

reduce $strings[] as $s (.; rdelete($s))

调用:

$ jq --argjson strings '["a","b"]' -f rdelete.jq input.json