传递多个对象给jq进行递归过滤操作
Passing Multiple Objects to jq for Recursive Filter Operation
我正在尝试使用 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(.$module)
替换 del(.META_BASIC_INFO)
并用 cat test.json | ./jq -f fsf_key_filter.jq --arg module META_BASIC_INFO
调用来测试,但这不起作用。
非常感谢对此的任何指导!
答案:
根据一些建议,我得出了以下有效且用户 JQ。
创新:
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 ]]))
您也可以使用 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”具有某种保留状态。)
似乎名称 module
是 1.5 中的关键字,因此 $module
将导致语法错误。您应该使用不同的名称。还有其他内置函数可以为您执行递归,请考虑使用它们而不是自己制作。
$ jq '(.. | objects | select(has($a))) |= del(.[$a])' --arg a "META_BASIC_INFO" Test.json
这是一个 "one-line" 使用 walk/1 的解决方案:
jq --arg d "META_BASIC_INFO" 'walk(if type == "object" then del(.[$d]) else . end)' input.json
如果 walk/1 不在你的 jq 中,这里是它的定义:
# 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
我正在尝试使用 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(.$module)
替换 del(.META_BASIC_INFO)
并用 cat test.json | ./jq -f fsf_key_filter.jq --arg module META_BASIC_INFO
调用来测试,但这不起作用。
非常感谢对此的任何指导!
答案:
根据一些建议,我得出了以下有效且用户 JQ。
创新:
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 ]]))
您也可以使用 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”具有某种保留状态。)
似乎名称 module
是 1.5 中的关键字,因此 $module
将导致语法错误。您应该使用不同的名称。还有其他内置函数可以为您执行递归,请考虑使用它们而不是自己制作。
$ jq '(.. | objects | select(has($a))) |= del(.[$a])' --arg a "META_BASIC_INFO" Test.json
这是一个 "one-line" 使用 walk/1 的解决方案:
jq --arg d "META_BASIC_INFO" 'walk(if type == "object" then del(.[$d]) else . end)' input.json
如果 walk/1 不在你的 jq 中,这里是它的定义:
# 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