私は GNU parallel を使用していますが、各並列コマンドに渡される個別の文字列を取得する方法を理解したいと思っています。
例えば、GNU Parallel ドキュメント現在のディレクトリから別のディレクトリにファイルを移動する方法を示します。
ls | parallel mv {} destdir
では、並列に渡された各ファイルを個別に取得/印刷する方法はありますか?
並列処理のケース
複数のサイトをチェックして記録する並列処理が必要です
- http 戻りコード (2xx、4xx、5xx)
- ソースURL
- 最終的なリンク先URL
- curl 終了コード
これを実行するコードは次のとおりです。
unset return_code_array
unset destination_url_array
unset exit_code_array
while read -r return_code_var destination_url_var exit_code_var; do
destination_url_array+=("$destination_url_var")
exit_code_array+=("$exit_code_var")
return_code_array+=("$return_code_var")
done < <(printf '%s\n' "${all_valid_URLs_array[@]}" | parallel -j 20 -k 'curl --max-time 20 -sL -o /dev/null -w "%{response_code} %{url_effective} " {}; printf "%s %s\n" "$?" ')
その結果、3 つの配列が作成され、エントリの各対応する行の HTTP 戻りコード、最終的な宛先 URL、および curl 終了コード ステータスが保持されますall_valid_URLs_array
。同時に、destination_url_var
ソース URL と一致するかどうかの比較など、それぞれに対して何らかの処理を実行する必要がありますが、parallels に渡された文字列を取得する方法がわかりません。
現在、このような処理のために上記のループの後に 2 番目のループを実行していますが、実現できるかどうかを知りたいです。
ありがとう。
答え1
あなたの例'curl … {}; printf "%s %s\n" "$?" '
(なぜ 2 番目%s
?)は、一重引用符で囲まれたシェル コードです。その中で、{}
複数回使用できます。
curl … {}; printf "%s %s\n" "$?" {}
あるいは、変数を作成して、必要な回数だけ使用することもできます。変数の名前は説明的なものにすることができます。これは利点です。もう 1 つの利点は、置換されるものが一般的に{}
長い文字列になる可能性があり、何度も置換すると、特定のシェルに渡されるコードが肥大化してしまう可能性があることですparallel
。私の意見では、置換を 1 回だけ行い、シェルに文字列を保存させて再利用させる方がよいと思います。
source_URL={}; curl … "$source_URL"; printf "%s %s\n" "$?" "$source_URL"
GNU の場合、シェル コードにparallel
埋め込むのは安全です{}
。この回答では、例外が明示的に言及されています。{}
シェルコードに埋め込まないでください。おそらくすでにご存知だと思いますが、この発言は一般の方に向けたものです。
read
メインループで調整する必要があることに注意してください。四変数。この方法では、ソース URL を の内部からparallel
メイン ループに転送し、そこで比較したりdestination_url_var
、必要な操作を実行したりできます。
それでも、このアプローチでは「必要なもの」は並列化されません。
からの出力を、curl
によって実行されるシェルコード内の別々の変数にキャプチャするとparallel
( の外部にキャプチャされるように印刷するのではなくparallel
)、比較(または何でも)を行うことができます。そこには、並列で。そして例えばprintf
条件付きでparallel
の内部が外部で期待される形式で出力を生成する限り、必要なロジックをどこに実装するかはあなた次第ですread
。
渡されるシェル コードは、parallel
依然として一重引用符で囲む必要があります。コードが大きくなるにつれて、このコード自体に一重引用符を使用する (埋め込む) 必要が生じる可能性があります。そうすると、引用符がやや複雑になり、読みにくくなります。このような状況では、独立して引用符で囲める別のスクリプトにコードを移動することを検討してください。メイン スクリプトから次のように呼び出します。
while read … ; done < <( … | parallel -j 20 -k 'path/to/separate_script {}' )
内では、separate_script
置換された文字列は次{}
のように表示されます$1
(二重引用符で囲む)。