【发布时间】:2016-01-28 00:04:09
【问题描述】:
假设我有:
function x {
echo "x"
}
call_func="x"
现在,我可以简单地使用eval,如下所示:
eval $call_func
但我想知道是否有其他方法可以调用名称存储在变量中的函数(如果存在):call_func。
【问题讨论】:
假设我有:
function x {
echo "x"
}
call_func="x"
现在,我可以简单地使用eval,如下所示:
eval $call_func
但我想知道是否有其他方法可以调用名称存储在变量中的函数(如果存在):call_func。
【问题讨论】:
你应该可以直接使用函数调用
$call_func
对于其他所有内容,请查看该答案:https://stackoverflow.com/a/17529221/3236102 它不是您直接需要的,但它显示了如何调用命令/函数的许多不同方式。
但让用户执行任意代码是不好的做法,因为它可能非常危险。这样做会更好:
if [ $userinput == "command" ];then
command
fi
这样,用户只能执行您希望他们执行的命令,甚至可以在输入错误时输出错误消息。
【讨论】:
call_func 中的变量将是一个字符串(取自用户输入)。只是把$call_func 回显它的内容,而不执行函数。
echo $($call_func),会发生什么?另外,也许尝试以不同的方式解决该问题。让用户执行任意代码是危险的!
echo是一样的。 :|我现在觉得很傻。
eval 中找到它(或者现在直接调用它)。不过,我希望有一个更干净的解决方法。
请注意:
变量保存数据,函数保存代码。
是bad practice to mix them,不要尝试。
是的,只需使用 var。如果 var a 是由a=ls 设置的,那么:
$ $a
将执行ls。第一个 $ 是 shell 的行提示符。
【讨论】:
x 中的echo 与call_func 的值相同。
eval "$cmd_with_args"
$the_command "${args[@]}" (其中args 是一个数组)以避免奇怪的分词问题。
如果您有 100 个五种不同类型的文件,并且您希望使用不同的函数来处理每种类型的文件,则可以创建一个切换函数,该函数包含一个带有嵌入式 case 语句的 for 循环。
您的目标是提供以下切换功能:
文件处理函数的名称。 ($1)
通过调用适当的文件收集函数得到文件名列表。
因此,您无需编写单独的函数来循环遍历每种文件,而只需使用一个函数即可。
#!/bin/sh
##################################################################
# Functions that gather specific kinds of filenames #
##################################################################
function getDogFiles
{
local -r TARGET_DIR="$1"
local fileGlobPattern="*.dog"
ls ${TARGET_DIR}${fileGlobPattern}
}
function getCatFiles
{
local -r TARGET_DIR="$1"
local fileGlobPattern="*.cat"
ls ${TARGET_DIR}${fileGlobPattern}
}
function getBirdFiles
{
local -r TARGET_DIR="$1"
local fileGlobPattern="*.bird"
ls ${TARGET_DIR}${fileGlobPattern}
}
function getFishFiles
{
local -r TARGET_DIR="$1"
local fileGlobPattern="*.fish"
ls ${TARGET_DIR}${fileGlobPattern}
}
function getFrogFiles
{
local -r TARGET_DIR="$1"
local fileGlobPattern="*.frog"
ls ${TARGET_DIR}${fileGlobPattern}
}
##################################################################
# Functions that process each type of file. #
##################################################################
function processDogFiles
{
local -r FILE_NAME="$1"
cat $FILE_NAME
}
function processCatFiles
{
local -r FILE_NAME="$1"
cat $FILE_NAME
}
function processBirdFiles
{
local -r FILE_NAME="$1"
cat $FILE_NAME
}
function processFishFiles
{
local -r FILE_NAME="$1"
cat $FILE_NAME
}
function processFrogFiles
{
local -r FILE_NAME="$1"
cat $FILE_NAME
}
##################################################################
# Functions to process all of the files #
##################################################################
function processItems
{
local -r PROCESSING_FUNCTION=$1
shift 1
for item in "$@"
do
$PROCESSING_FUNCTION "$item"
done
}
function processAnimalFiles
{
local -r TARGET_DIR="$1"
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[@]}"
【讨论】: