4行のテキストファイルがあり、各行には1、2、3、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
ただし、0を使用する代わりに変数()を使用して呼び出す必要があります。どうすればいいですか?
答え1
シェルコードに含めると{}
コマンドインジェクションの脆弱性が発生するため、常に悪い考えです。データを別々の(コードではなく)パラメータとして渡すことは、常に良いです。
また、/-I
がない場合は、引用符とバックスラッシュをブロックして先行スペースを削除します。 GNU(すでにGNU拡張を使用しているため使用する必要がある)の場合は、各入力行を別々の引数として渡すことをお勧めします-d
-0
xargs
-P
-d '\n'
xargs -a txt -rd'\n' -P2 -n1 bash -c 'foo "$2" "$1"' bash "$a"
(インラインシェルスクリプトでは、sumと呼ばれる別の引数で、現在の行の内容を使用して各入力行bash
に対して1回呼び出されます。)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