【问题标题】:Create 256 functions that do the same thing - creating a case-insensitive function - one liner to pass all parameters to a function?创建 256 个执行相同操作的函数 - 创建一个不区分大小写的函数 - 一个将所有参数传递给函数的衬垫?
【发布时间】:2013-10-22 17:58:00
【问题描述】:

我想创建 256 个做同样事情的函数

基本上我想要一个能够不区分大小写地调用的函数。

示例:我希望 applepie() 能够不区分大小写地调用:

applepie(){

for B in "$@";
do
another_function_in_my_bash_profile $B
blah blah 
# more stuff ...   
done

}

最直接的方法是用一些大写字母声明另外 255 个函数:

Applepie(){

for B in "$@";
do
another_function_in_my_bash_profile $B
blah blah 
# more stuff ...   
done

}

aPplepie(){

for B in "$@";
do
another_function_in_my_bash_profile $B
blah blah 
# more stuff ...   
done

}

...

一直到

APPLEPIE(){

for B in "$@";
do
another_function_in_my_bash_profile $B
blah blah 
# more stuff ...   
done

}

总共有 256 个(2 的 8 次方)

可以快速完成吗?还是有更“内置”的方法,比如

case-insensitive appelepie(){

for B in "$@";
do
another_function_in_my_bash_profile $B
blah blah 
# more stuff ...   
done

}

或者是否可以这样做

case-insensitive APPLEPIE(){
  command -pass_all_parameters applepie
}

可以将所有参数传递给applepie,而不是使用for循环for B in "$@";

【问题讨论】:

    标签: linux macos bash function terminal


    【解决方案1】:

    您可以通过定义全小写的函数名称并使用bash 的缺少命令名称的陷阱来伪造不区分大小写的函数名称(需要bash 4,您需要在OS X 上自行安装):

    command_not_found_handle () {
        cmd_name=${1,,}
        shift
        $cmd_name "$@"
    }
    

    因此,如果apple 是一个函数,但您尝试将其调用为ApPlE,则使用命令作为参数调用command_not_found_handle。第一行采用第一个参数 (ApPlE) 并将其小写。然后它会尝试使用原始参数运行apple

    【讨论】:

    • +1 表示非常聪明;但是有没有办法在较低版本的 bash 中做到这一点?
    • 小写很容易:cmd_name=$(tr '[A-Z]' '[a-z]' <<< "$1")。但是,不能捕获“找不到命令”。您可以如上所述定义command_not_found_handle,然后将其用作DEBUG 陷阱,但请参阅bash 手册页中的extdebug 选项了解更多详细信息。我不认为你可以用DEBUG 完全模拟bash 4 的功能。
    【解决方案2】:

    这是一个相当迟钝的答案,绝对不是单行的,但在bctr 的帮助下,这是如何在 中完成的(适用于) :

    funcname="applepie"
    
    strlen=${#funcname}
    numcombos=$((2 ** strlen))
    
    for ((i=1; i<numcombos; i++)); do
        binstr=$(echo "obase=2; $i" | bc )
        zlen=$((1+strlen-${#binstr}))
        binstr=$(printf "%0${zlen}x" 0)${binstr}
        binstr=${binstr:1:$strlen}
        casename=""
        for ((j=0; j<strlen; j++)); do
        if [ ${binstr:$j:1} = 1 ]; then
            casename=${casename}$(tr '[a-z]' '[A-Z]' <<< ${funcname:$j:1})
        else
            casename=${casename}${funcname:$j:1}
        fi
        done
        alias ${casename}=${funcname}
    done
    

    这会执行以下操作;

    • 获取函数名的长度
    • 计算案例组合的数量 (2^n)
    • 循环遍历每个组合
    • 将组合数转换成二进制数字串
    • 调整二进制数字字符串,使其与函数名长度相同
    • 通过函数名的每个字符和二进制数字字符串进行索引,并且仅当对应的二进制数字为 1 时才会更改 toupper() 大小写
    • 将字符重新组合成字符串
    • 从每个组合到函数名的 bash 别名

    假设函数已定义,并且名称全小写。

    【讨论】:

      【解决方案3】:

      这是另一种使用纯 bash 和递归函数的方法。当我看到递归函数时,我通常会跑一英里,但在这种情况下它工作得非常好:

      funcname="applepie"
      
      function cr {
          if [ "$1" ]; then
              cr "${1:1:${#1}}" "${2:1:${#2}}" "${3}${1:0:1}"
              cr "${1:1:${#1}}" "${2:1:${#2}}" "${3}${2:0:1}"
          else
              alias $3=$funcname
          fi
      }
      
      cr $funcname $(tr '[a-z]' '[A-Z]' <<< $funcname) ""
      

      【讨论】:

        猜你喜欢
        • 2019-04-28
        • 2011-03-09
        • 1970-01-01
        • 2013-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多