コマンド出力から行を読み取る方法はありますか?


8

ファイルを出力するための前処理コマンドがあります

./preprocess.sh > preprocessed_file 

そして、preprocessed_fileこのように使用されます

while read line
do

    ./research.sh $line &

done < preprocessed_file 

rm -f preprocessed_file

while read linepreprocessed_fileに出力する代わりに、出力をパーツに送る方法はありますか?このtempを使用する以外にもっと良い方法があるはずだと思いますpreprocessed_file

回答:


8

bash プロセスの置換を使用できます。

while IFS= read -r line; do
  ./research.sh "$line" &
done < <(./preprocess.sh)

プロセス置換のいくつかの利点:

  • 一時ファイルを保存する必要はありません。
  • よりよい性能。多くの場合、別のプロセスからの読み取りは、ディスクへの書き込みよりも速く行われ、その後、再度読み込まれます。
  • パラメータと変数の展開、コマンド置換、および算術展開と同時に実行されるため、計算時間を節約できます。

二重左矢印(<<)はどういう意味ですか?
マーカスソーントン

@MarcusThornton:<リダイレクトですが、<(...)プロセス置換構文です。詳しくは、gnu.org / software / bash / manual / html_node / をお読みください。
cuonglm 2014

とった。<(...)構文の一部です。
マーカスソーントン

2
必ずしも速いとは限りません。パイプreadから読み取るときは、一度に1バイトを読み取る必要がありますが、より大きなチャンクを読み取ることで物事を最適化し、通常のファイルから読み取るときに逆方向にシークできるためです。最善の方法はwhile read、可能な限り最初からループを完全に回避することです。またIFS= read -r line、行をに読み込む必要があることにも注意してください$line。そして、ここで$line引用符を付けずに(split + glob演算子を呼び出す)ままにしても、おそらく意味がありません。
ステファンChazelas

1
@mikeserv、コマンドは、端末に送られるときに、出力を(フルバッファーではなく)ラインバッファーにすることがよくあります。ここではread、パイプから読み取るときに組み込みシェルが一度に1文字ずつ読み取ると言っています(パイプのもう一方の端にあるreadものを知る方法がなくても)。これは、while readループが非常に遅い理由の1つです。
ステファンChazelas

15

はい!プロセスパイプを使用できます|

./preprocess.sh |
    while IFS= read -r line
    do
        ./research.sh "$line" &
    done

プロセスパイプは、あるプロセスの標準出力(stdout)をstdin次のプロセスの標準入力()に渡します。

オプションで、aの後に改行文字を置き|、コマンドを次の行に拡張できます。

注:a|bと同じb < <(a)ですが、マジックファイルがなく、読みやすい順序で、特にパイプラインが長くなる場合に役立ちます。

a|b|c に相当 c < <(b < <(a))

そして

a|b|c|d|e です e < < (d < <(c < <(b < <(a))))


3
注:パイプを使用したこのソリューションには、プロセス置換よりも移植性が高いという利点があります(ダッシュのような一部のPOSIXシェルではサポートされていません)。移植性に関しては、パイプの右側がサブシェル(シェルによって異なります)で実行される可能性があるため、副作用(変数の設定など)がシェルスクリプトの環境に影響を与えない場合があります。
vinc17 2014

変数の参照$lineを二重引用符で囲むのが一般的により安全です(たとえば、スクリプトで./research.sh "$line" &)。
G-Manは 'Reinstate Monica'

1
@ G-Manおそらくこのコンテキストにはありません。場合はresearch.sh、コマンドライン引数の配列を持つ作品とは、$line最初の引数が引用、「1」と第二引数「2」であることを意図して、例えば、「1〜2」を、である$line代わりに、最初の引数はなります-それは不可能になります「1つ2つ」で2つ目はありません...
ゴールドロック'25

2
" a|bb < <(a) " と同等です -近いですが、完全ではありません。パイプバージョンでは、パイプの両側がサブシェルで実行されますが、プロセス置換バージョンでは、置換されたプロセスのみがサブシェルでa実行され、現在実行中のシェルレベルのスコープで実行されます。これは、内部で設定される変数の範囲に重要な影響を及ぼしますa
Digital Trauma '25
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.