私はシェルスクリプトに最初に触れましたが、パラメータなしで1つ以上のパラメータを使用して別の関数を呼び出すのではなく、関数自体を呼び出すことができるかどうかを知りたいです。最初のパラメータは呼び出す関数の名前、残りのパラメータはそれぞれ呼び出す関数のパラメータです。
背景知識として、私は説明のために上記の例で呼び出されたいくつかの組み込みOpenFOAM関数、つまりおよびをrunParallel
使用するシェルスクリプトを作成したいと思います。これらの関数は、名前が示すようにさまざまな操作を実行し、シリアルモードまたはパラレルモードでコマンドを実行します。runApplication
runSerial
OpenFOAMのシミュレーションはいくつかの関数呼び出しで構成されています。
#!/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
こんなものに置き換えることができるか悩んでいたのに
#!/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"
runSerialOrParallel
現在私は、関数が自分で呼び出す必要がある関数パラメータを解釈する方法について心配しています。それでは、functionTwo
シリアルまたはパラレルで実行し、パラメータがある場合はfunctionTwo
内部的にこれを達成しますかrunSerialOrParallel
?
どんな助けでも大変感謝します。この質問について私は簡単に見つけることができましたが、見つからなかった神聖な冒涜的な答えがある場合は許してください。
乾杯!
(編集者がいくつかのことを明確にしてくれることを願っています。残念です。)
ベストアンサー1
Bourneのようなシェル"$@"
(引用符が重要です!)では、拡張はスクリプト内のすべての引数に適用されるか、関数内で拡張されると関数に適用されます。したがって、次のようになります。
runSerialOrParallel()
{
if [ "$n_core" -eq 1 ]; then
runSerial "$@"
else
runParallel "$@"
fi
}
自分が受け取ったのと同じ引数を使用してrunSerialOrParallel
呼び出されますrunSerial
。runParallel
最初の引数が関数名で、次の引数が関数に渡される場合、関数は次のようになりますrunSerial
。
runSerial() {
printf 'Running "%s" with %u argument%s:\n' "$1" "$(($# - 1))" "${3+s}"
"$@"
}
(最初の引数が関数なのか、外部のコマンドなのか、組み込み関数なのかはここでは違いはありません。)
または:
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" "$@"
}
(少なくとも2つの引数が指定されている場合、2番目(最初は3番目)引数が指定されている場合は、${2+s}
「引数」を複数の「引数」に変換するように拡張されます。)s
$funcName
$ 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