调用名称存储在 bash 中的变量中的函数

Invoke function whose name is stored in a variable in bash

假设我有:

function x {
    echo "x"
}
call_func="x"

现在,我可以简单地使用 eval 如下:

eval $call_func

但我想知道是否有其他方法可以调用名称存储在变量中的函数(如果存在):call_func.

您应该可以直接使用

调用该函数
$call_func

对于其他所有内容,请查看答案: 它不直接是您需要的,但它显示了如何调用命令/函数的许多不同方式。

虽然让用户执行任意代码是不好的做法,因为它可能非常危险。这样做会更好:

if [ $userinput == "command" ];then
    command
fi

这样,用户只能执行您希望他们执行的命令,如果输入不正确,甚至可以输出错误消息。

请注意:

Variables hold data, functions hold code.

bad practice to mix them,请勿尝试


是的,只需使用一个变量。如果 var a 由 a=ls 设置,则:

$ $a

将执行ls。第一个$是shell.

的行提示符

文件处理用例:模拟传递匿名函数

如果您有 100 个五种不同类型的文件,并且您想要不同的函数来处理每种类型的文件,您可以创建一个切换函数,其中包含一个 for 循环和一个嵌入式 case声明。

您的目标是为切换功能提供:

  1. 文件处理函数的名称。 ($1)

  2. 通过调用适当的文件收集函数的文件名列表。

因此,您无需编写单独的函数来遍历每种文件,只需使用一个函数即可。

#!/bin/sh

##################################################################
#        Functions that gather specific kinds of filenames       #
##################################################################

function getDogFiles
{
    local -r TARGET_DIR=""
    local fileGlobPattern="*.dog"

    ls ${TARGET_DIR}${fileGlobPattern}
}

function getCatFiles
{
    local -r TARGET_DIR=""
    local fileGlobPattern="*.cat"

    ls ${TARGET_DIR}${fileGlobPattern}
}

function getBirdFiles
{
    local -r TARGET_DIR=""
    local fileGlobPattern="*.bird"

    ls ${TARGET_DIR}${fileGlobPattern}
}

function getFishFiles
{
    local -r TARGET_DIR=""
    local fileGlobPattern="*.fish"

    ls ${TARGET_DIR}${fileGlobPattern}
}

function getFrogFiles
{
    local -r TARGET_DIR=""
    local fileGlobPattern="*.frog"

    ls ${TARGET_DIR}${fileGlobPattern}
}

##################################################################
#            Functions that process each type of file.           #
##################################################################

function processDogFiles
{
    local -r FILE_NAME=""
    cat $FILE_NAME
}

function processCatFiles
{
    local -r FILE_NAME=""
    cat $FILE_NAME
}

function processBirdFiles
{
    local -r FILE_NAME=""
    cat $FILE_NAME
}

function processFishFiles
{
    local -r FILE_NAME=""
    cat $FILE_NAME
}

function processFrogFiles
{
    local -r FILE_NAME=""
    cat $FILE_NAME
}

##################################################################
#            Functions to process all of the files               #
##################################################################

function processItems
{
    local -r PROCESSING_FUNCTION=
    shift 1
    
    for item in "$@"
    do
        $PROCESSING_FUNCTION "$item"
    done
}

function processAnimalFiles
{
    local -r TARGET_DIR=""

    shift 1  # Remove the target directory from the argument list.

    local -ar FILE_TYPES=( "$@" )

    processingPrefix="process"
    processingSuffix="Files"

    gatheringPrefix="get"
    gatheringSuffix="Files"

    for fileType in "${FILE_TYPES[@]}"
    do
        case "$fileType" in
            Dog | Cat | Bird | Fish | Frog)
                fileProcessingFunction="${processingPrefix}${fileType}${processingSuffix}"
                fileGatheringFunction="${gatheringPrefix}${fileType}${gatheringSuffix}"
                processItems "$fileProcessingFunction" $($fileGatheringFunction "$TARGET_DIR")   #    The second argument expands to a list of file names. 
                ;;
            *)
                echo "Unknown file type: ${fileType} file." >> /var/log/animalFiles.err.log
                ;;
        esac
    done
}

########################################### ################################

local -a animalFiles=(Dog Cat Bird Fish Frog Truck)
processAnimalFiles "/opt/someapp/data/" "${animalFiles[@]}"