如何传递给 bash 函数 2 可变参数列表?

发布于 2025-01-09 21:15:24 字数 350 浏览 1 评论 0原文

我正在寻找一种抽象通用命令的方法:

find src app -name "*.hs" -exec grep -H "foo" \{\} \;

到 bash/zsh 函数,例如:

find $1 -exec grep -H $2 \{\} \;

上面不是解决方案,因为我想使用给定的语法传递参数列表,例如: findgrep "src -姓名'.hs'" "foo"。 在这里,我们可以说 grep 的参数实际上是一个单词,然后传递参数列表的其余部分来查找,但应该有一种更通用的方法吗?有没有办法部分应用 bash 函数?

提前致谢!

I'm looking for a way to abstract common command:

find src app -name "*.hs" -exec grep -H "foo" \{\} \;

to a bash/zsh function like:

find $1 -exec grep -H $2 \{\} \;

Above is not a solution as I'd like to pass lists of arguments for example with a given syntax: findgrep "src -name '.hs'" "foo".
Here we could say that argument to grep is ever really going to be a single word and then pass the rest of argument list to find but there ought to be a more general way? Is there a way to sort of partial apply a bash function?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

茶花眉 2025-01-16 21:15:24

一般来说,你不能这样做,因为每个单独的参数只是一个常规字符串; shell 没有明确的列表类型。

要传递两个“组”参数,您需要定义某种您的函数可以识别的“哨兵”。例如,

findgrep () {
    args=()
    for x; do
        shift
        [[ $x == ::: ]] && break
        args+=("$x")
    done
    find "${args[@]}" -exec grep -H "$@" {} \;
}

findgrep src -name ".hs" ::: foo

findgrep 会将参数添加到数组 args 中,直到看到参数 :::,此时它将忽略 ::: 但停止迭代。现在,您可以使用 args 作为 find 的第一组参数,并将 $@ 中剩下的任何内容作为第二组。

找到一个有效的哨兵可能很困难,因为从理论上讲,实际上没有任何字符串不能成为 find 的有效参数。另一种方法是使用商定的全局数组来存储一组或两组。

findgrep () {
    find "${findgrepargs[@]}" -exec grep -H "$@" {} \;
}

findgrepargs=(src -name .hs)
findgrep foo

或者使用 nameref 将任意数组的名称传递给函数。

findgrep () {
    declare -n findargs=$1
    shift
    findgrep "${findargs[@]}" -exec grep -H "$@" {} \;
}

x=(src -name .hs)
findgrep x foo

In general, you cannot do that, as every individual argument is just a regular string; the shell has no distinct list type.

To pass two "groups" of arguments, you'll need to define some sort of "sentinel" that your function can recognize as such. For example,

findgrep () {
    args=()
    for x; do
        shift
        [[ $x == ::: ]] && break
        args+=("$x")
    done
    find "${args[@]}" -exec grep -H "$@" {} \;
}

findgrep src -name ".hs" ::: foo

findgrep will add arguments to the array args until it sees the argument :::, at which point it will ignore ::: but stop iterating. Now you can use args as the first group of arguments to find, and whatever is left in $@ as the second group.

Finding a valid sentinel could be difficult, as there's really no string that couldn't, in theory, also be a valid argument to find. An alternative would be to use an agreed-upon global array to store one or both sets.

findgrep () {
    find "${findgrepargs[@]}" -exec grep -H "$@" {} \;
}

findgrepargs=(src -name .hs)
findgrep foo

or to use a nameref to pass the name of an aribitary array to the function.

findgrep () {
    declare -n findargs=$1
    shift
    findgrep "${findargs[@]}" -exec grep -H "$@" {} \;
}

x=(src -name .hs)
findgrep x foo
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文