chamar função pelo nome com argumentos
Sou bastante novo no front de script de shell e queria saber se é possível chamar uma função que por si só chama outra função sem nenhum, um ou vários argumentos. O primeiro argumento seria o nome da função a ser chamada, todos os outros argumentos são um argumento da função a ser chamada.
Como pano de fundo, desejo escrever um script de shell para usar algumas funções integradas do OpenFOAM, a saber runParallele runApplication, que, para esclarecimento, chamei runSerialno exemplo acima. Essas funções fazem coisas diferentes, como o nome sugere, elas executam um comando no modo serial ou paralelo.
Uma simulação em OpenFOAM é composta de várias chamadas de função e tudo que eu quero fazer é encurtar o código para que, em vez disso
#!/bin/sh
# $n_core is a user input how many cores to use printf 'On how many cores do you want to run the simulation?' read -r n_core if [ $n_core -eq "1" ]; then
runSerial "functionOne" # no arguments here
runSerial "functionTwo" "arg1"
runSerial "functionThree" "arg1" "arg2"
...
else
runParallel "functionOne" # no arguments here
runParallel "functionTwo" "arg1"
runParallel "functionThree" "arg1" "arg2"
...
fi
Eu estava me perguntando se eu poderia substituir isso por algo assim
#!/bin/sh
runSerialOrParallel()
{
if [ $n_core -eq "1" ]; then runSerial "$1" "$2" ... else runParallel "$1" "$2" ... fi } # $n_core is a user input how many cores to use
printf 'On how many cores do you want to run the simulation?'
read -r n_core
runSerialOrParallel "functionOne" # no arguments here
runSerialOrParallel "functionTwo" "arg1"
runSerialOrParallel "functionThree" "arg1" "arg2"
No momento, estou preso à questão de como explicar os argumentos da função que minha runSerialOrParallelfunção deve chamar a si mesma. Portanto, se eu quiser functionTwoser executado em série ou paralelo, com um argumento para functionTwosi mesmo, como faço isso acontecer internamente runSerialOrParallel?
Qualquer ajuda seria muito apreciada e por favor me perdoe se houver uma resposta profana para essa pergunta que eu poderia facilmente ter encontrado, mas não encontrei.
Felicidades!
(Espero que a edição tenha esclarecido algumas coisas, meu mal ..)
Respostas
Em shells tipo Bourne "$@"(observe que as aspas são importantes!) Se expande para todos os argumentos do script, ou função se expandida dentro de uma função, então aqui:
runSerialOrParallel()
{
if [ "$n_core" -eq 1 ]; then
runSerial "$@" else runParallel "$@"
fi
}
Faria runSerialOrParallelinvocar runSerialou runParallelcom os mesmos argumentos que se recebeu. Se o primeiro argumento for um nome de função e os seguintes mais argumentos a serem passados para essa função, sua runSerialfunção poderia ser algo como:
runSerial() {
printf 'Running "%s" with %u argument%s:\n' "$1" "$(($# - 1))" "${3+s}"
"$@"
}
(note que se o primeiro argumento é uma função, comando externo ou embutido não faz diferença aqui).
Ou:
runSerial() {
funcName=${1?No function specified}
shift # removes the func name from the arguments
printf 'Running "%s" with %u argument%s:\n' "$funcName" "$#" "${2+s}" "$funcName" "$@"
}
(o ${2+s}expande para sse o segundo argumento (inicialmente terceiro) for especificado para transformar "argumento" em "argumentos" no plural quando pelo menos dois argumentos para $funcNameforem especificados).
$ runSerial echo foo bar
Running "echo" with 2 arguments:
foo bar
$ runSerial echo foo Running "echo" with 1 argument: foo $ n_core=1
$ runSerialOrParallel echo foo
Running "echo" with 1 argument:
foo