如何编写委托给jq的fish函数?

Cub*_*bre 2 shell fish jq

我正在尝试编写一个名为fish函数的函数jq_select_keys,它从给定的JSON中选择一个键的子集.

jq咒语做这件魔术是:

jq -r "with_entries(select([.key] | inside([\"bar\",\"baz\",\"qux\"])))" file.json
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试定义一个名为jq_select_keys的方便函数,它将获取我感兴趣的文件名和密钥,并吐出子集.这是我想出的:

function jq_select_keys --description 'Selects given keys from json input'
  set key_names (for key in $argv[2..-1]; echo "\\\"$key\\\""; end)
  set key_names_joined (string join "," $key_names)
  set jq_args "\"with_entries(select([.key] | inside([$key_names_joined])))\""
  echo "Command: jq -r $jq_args $argv[1]"
  jq -r $jq_args $argv[1]
end
Run Code Online (Sandbox Code Playgroud)

当我在我的鱼壳jq_select_keys foo.json bar baz qux上运行时,我得到以下输出:

Command: jq -r "with_entries(select([.key] | inside([\"bar\",\"baz\",\"qux\"])))" foo.json
with_entries(select([.key] | inside(["bar","baz","qux"])))
Run Code Online (Sandbox Code Playgroud)

现在,有趣的是我可以复制粘贴echo语句的输出,并按预期运行.但我得到的输出只是我传递给jq的查询字符串.

我是shell编程的新手,所以我可能搞砸了我的引号.但除此之外,我不知道如何让这件事发挥作用!

fah*_*aho 5

我是shell编程的新手,所以我可能搞砸了我的引号.

基本上就是这样.

看来你添加了一层太多的引号.

在鱼(以及大多数其他贝壳,包括例如bash和zsh)中,引号仅在字面上使用时对shell特殊.

这意味着,当一个变量包含"some string",然后echo $variable将打印"some string"-这意味着echo接收到的命令字符串用引号(注:庆典也将适用于此字拆分,因此它实际上会得到"somestring",即使你可能认为它是引用) .

我建议你逐个完成你的功能,只echo需要变量.然后想象你传递,准确的字符串jq-将它的工作?

比如$key_names:

set key_names (for key in $argv[2..-1]; echo "\\\"$key\\\""; end)
Run Code Online (Sandbox Code Playgroud)

这样做的目的显然是为了逃避所有密钥(从第二个开始的参数)以供使用jq.这意味着他们需要被引用一次.它们不需要再次引用,因为shell不关心非文字引号.

所以任何键都应该是这样的"key".

但是当我们放

printf '%s\n' $key_names
Run Code Online (Sandbox Code Playgroud)

(将在自己的行上打印每个键)

在此之后,我们看到了

\"bar\"
\"baz\"
\"qux\"
Run Code Online (Sandbox Code Playgroud)

这是2个引述的层次!引号本身,以及逃避它们的反斜杠.

所以让我们删除一个:

set key_names($ argv中的键[2 ..- 1]; echo"\"$ key \""; end)

这将导致"bar","baz""qux".

(这可以set key_names \"$argv[2..-1]\"通过使用鱼的笛卡尔产品简化 )

现在为下一点:

set jq_args "\"with_entries(select([.key] | inside([$key_names_joined])))\""
Run Code Online (Sandbox Code Playgroud)

你在这里的目的是像你一样运行它

jq -r "with_entries(select([.key] | inside([\"bar\",\"baz\",\"qux\"])))" foo.json
Run Code Online (Sandbox Code Playgroud)

在命令行上.但是当你使用变量时,你不需要再次引用它们中的字符串 - 一旦分配了值,所有的分裂和其他扩展都已经发生,并且当替换变量时不会再发生.

因此,只需删除转义的引号即可

set jq_args "with_entries(select([.key] | inside([$key_names_joined])))"
Run Code Online (Sandbox Code Playgroud)

你的功能应该工作.

结果是:

function jq_select_keys --description 'Selects given keys from json input'
    set key_names \"$argv[2..-1]\"
    set key_names_joined (string join "," $key_names)
    set jq_args "with_entries(select([.key] | inside([$key_names_joined])))"
    echo "Command: jq -r $jq_args $argv[1]"
    jq -r $jq_args $argv[1]
end
Run Code Online (Sandbox Code Playgroud)