xargsと個別の変数を使用して関数を並列化する

xargsと個別の変数を使用して関数を並列化する

各行に 1、2、3、4 が含まれる 4 行のテキスト ファイルがあります。また、並列化したい関数があります。foo() { echo "$1 is not $2"; }

関数をエクスポートします:export -f foo

ここで、並列化に使用するテキスト ファイルからのパラメーターを使用して関数を呼び出しますxargsそしてa=0また、関数のパラメータとして変数 ( ) を使用したいと思います。そのため、関数を次のように呼び出します。cat txt | xargs -I "{}" -P 2 bash -c 'foo {} $a'

しかしこれは変数 ( a=0) を無視します。そして出力は次のようになります:

「1は違う」...「4は違う」など

呼び出すと、cat txt | xargs -I "{}" -P 2 bash -c 'foo {} 0'正しく動作し、正しい出力が得られます。

「1は0「…4は0「など」

しかし、ゼロではなく変数 ( a=0) を使用して呼び出す必要があります。どうすればいいでしょうか?

答え1

シェル コードに を埋め込むことは{}、コマンド インジェクションの脆弱性を招くため、常に悪い考えです。データを別の (コード以外の) 引数として渡す方が常に良いでしょう。

また-I-d/がない-0場合でも、引用符やバックスラッシュで詰まってしまい、先頭の空白が削除されます。GNU の場合xargs(すでに GNU 拡張機能を使用しているため、使用する必要があります)、入力の各行を個別の引数として渡すには、-Pを使用するのが最適です。-d '\n'

xargs -a txt -rd'\n' -P2 -n1 bash -c 'foo "$2" "$1"' bash "$a"

(入力の各行に対してと現在の行の内容を別々の引数として1 つのbash呼び出しを呼び出します。これらの引数はインライン シェル スクリプトでととして参照されます)。1$a$1$2

または、以下を使用します-I:

xargs -a txt -rd'\n' -P2 -I'{}' bash -c 'foo "$1" "$2"' bash {} "$a"

ここで、 に切り替えることができます。 には、個別のシェル呼び出しを実行したり、 のように関数をエクスポートしたりすることなく、関数を含め、 GNU 風の並列処理を実行できる自動ロード可能zshな関数があります。zargsxargsxargs

$ autoload zargs
$ foo() print -r - $1 is not $2
$ zargs -P2 -I {} {1..4} -- foo {} $a
1 is not foo
2 is not foo
3 is not foo
4 is not foo

答え2

GNU Parallel の場合は次のようになります。

foo() { echo "$1 is not $2"; }
export -f foo
seq 4 > txt
a=0
cat txt | parallel foo {} $a

関連情報