
各行に 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
な関数があります。zargs
xargs
xargs
$ 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