web-dev-qa-db-ja.com

関数をコマンド `parallel`(GNU)で使用できるようにする方法は?

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

ファイルの各行で関数を定義しなくても、関数fparallelで使用できるようにする方法はありますかCommands.txt

7
Remi.b

基本的に3つのオプションがあります。

  1. export -f(これはPOSIX以外のbash機能です)
  2. 呼び出しごとに関数を定義するシェルを実行する
  3. 関数をシェルスクリプトに移動し、代わりにそれを実行する

オプション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に注意してください)。

6
Chris Down

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