Bashでは、引数が「整数」であるecho
以外に何もしない関数を考えてみましょう。
f () { num="${!1}"; echo $num is an integer; }
number=12
f number
# 12 is an integer
関数f
を使用するいくつかのコマンドをファイルに書き込んでから、関数parallel
(GNU)を使用してこれらのコマンドを並行して実行したいと思います。
# Write Commands to the file `Commands.txt`
rm Commands.txt
touch Commands.txt
for i in $(seq 1 5)
do
echo "number=$i; f number" >> Commands.txt
done
source
を使用すると、すべて正常に動作します
source Commands.txt
1 is an integer
2 is an integer
3 is an integer
4 is an integer
5 is an integer
しかし、コマンドを並行して実行しようとすると、関数f
が見つからないことが返されます
parallel :::: Commands.txt
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
ファイルの各行で関数を定義しなくても、関数f
をparallel
で使用できるようにする方法はありますかCommands.txt
?
基本的に3つのオプションがあります。
export -f
(これはPOSIX以外のbash機能です)オプション1はおそらく最も簡単にデモンストレーションできるので、それを示します。
$ f() { num=$1; echo "$num is an integer"; }
$ export -f f
$ cat Commands.txt
number=1; f "$number"
number=2; f "$number"
number=3; f "$number"
number=4; f "$number"
number=5; f "$number"
$ parallel :::: Commands.txt
1 is an integer
2 is an integer
3 is an integer
4 is an integer
5 is an integer
Commands.txt
の母集団はエラーになっている可能性が高いことに注意してください。数値を渡すにはf "$number"
のCommands.txt
が必要です。リテラル文字列「number」を渡すf number
ではありません。これを生成するスクリプトはecho "number=$i; f \"\$number\""
を実行する必要があります(エスケープは、echo
時に$number
が解釈されないようにするために重要です。または、文字列を終了する"
sに注意してください)。
Bashは、環境変数を介して関数をエクスポートできます。
export -f f
これはbash機能であり、shファミリーの他のシェルでは使用できないことに注意してください。
または、関数をスクリプトにします。スクリプトと関数は、関数定義行を除いて同じ構文を持っています。
#!/bin/bash
num="${!1}"; echo $num is an integer;
その場合は、スクリプトに渡す変数をエクスポートする必要があります。Command.txt
の行は次のようになります。
export number=1; f number
または
number=1 f number