同一个 bash 函数怎么能以多个名称为人所知?

How can the same bash-function be known under multiple names?

我们有几个相当大的函数,它们之间的差别很小——只有一行。

我想将它们全部替换为一个函数——其中一行由 FUNCNAME:

决定
function single () {
    ....
    case $FUNCNAME in
    variant1)
        foo=meow
        ;;
    variant2)
        foo=woof
        ;;
    esac
    ....
}

处理不同名称的函数内代码很简单(见上文)。我的问题是以不同的名称注册相同的代码(函数体)...

如何让同一个函数在不同的别名下为人所知?简单地使用 alias variant1=single 是行不通的。例如,下面的代码运行后:

shopt -s expand_aliases
for v in variant1 variant2 ... variantN
do
     alias $v=single
done

新变体不知何故仍然未知——即使 type -t variant1 正确打印 alias.

除了通过 alias.

之外,我(个人)不知道有什么方法可以为函数赋予多个名称

使用 alias 的一种(相对)简单的方法是将 'variant' 的名称作为第一个参数传递给函数调用。然后,您在函数中做的第一件事就是测试第一个参数是否为 'variant' 名称之一。

考虑:

func1 () {
case "" in
    func2) currFUNCNAME="func2"; shift      ;;  # shift remaining args into positions ,  ... $n
    func3) currFUNCNAME="func3"; shift      ;;  # shift remaining args into positions ,  ... $n
        *) currFUNCNAME="${FUNCNAME}"       ;;  # func1 called directly so  is not a known variant
esac
echo "currFUNCNAME = ${currFUNCNAME}"
}

定义几个变体:

alias func2='func1 func2'
alias func3='func1 func3'

现在进行一些测试:

$ func1
currFUNCNAME = func1

$ func2
currFUNCNAME = func2

$ func3
currFUNCNAME = func3

使用 OP 示例 shopt/for 代码动态创建函数:

shopt -s expand_aliases

for v in func2 func3
do
     alias "$v"="func1 $v"
done

运行我们再次测试:

$ func1
currFUNCNAME = func1

$ func2
currFUNCNAME = func2

$ func3
currFUNCNAME = func3

虽然此时如果要在此脚本中使用这些函数,那么为什么不编辑脚本以使用额外的输入 arg 调用主要函数...?

效果可以模拟为:

#!/usr/bin/env bash

function single () {
    case $FUNCNAME in
    variant1)
        foo=meow
        ;;
    variant2)
        foo=woof
        ;;
    esac
    echo $foo
}   

for variant in variant1 variant2; do
    eval "$(declare -f single|perl -pe 's/single/'$variant'/ if ($. == 1)')"
done

unset -f single

variant1
# meow
variant2
# woof

尽管功能代码重复,出于安全原因不建议使用eval

更新 1 第二种方法

#!/usr/bin/env bash

single(){
    case ${FUNCNAME[1]} in
    variant1)
        foo=meow
        ;;
    variant2)
        foo=woof
        ;;
    esac
    echo $foo
}   

variant1(){ single "$@"; }
variant2(){ single "$@"; }

variant1
# meow
variant2
# woof

另一个基于 alias 的选项依赖于用户定义的变量(而不是命令行参数)...

假设我们的用户定义变量命名为$myalias:

func1 () {

currFUNCNAME="${myalias:-${FUNCNAME}}"
echo "currFUNCNAME = ${currFUNCNAME}"

}

注意:显然我们需要选择一个我们确定没有使用的变量;从 OP 的评论来看,这听起来不应该是一个问题(即,只需选择一个当前未在 OP 脚本中使用的新变量名称)

定义我们的别名首先给$myalias赋值,然后调用主函数:

shopt -s expand_aliases

for v in func2 func3
do
     alias "$v"="myalias='$v'; func1"
done

现在进行一些测试:

$ func1
currFUNCNAME = func1

$ func2
currFUNCNAME = func2

$ func3
currFUNCNAME = func3

您可以使用别名为同一函数定义新名称


# attach a bash shell to a running docker container
function dexb {
    docker exec -it "" /bin/bash
}

# attach a sh shell to a running docker container
function dexs {
    docker exec -it "" /sh
}

# Now instead of creating another function say 'dex' with the same 
# content as the function 'dexb'

# I'll just create an alias

alias 'dex'='dexb'