whileループなしでbashの読み取り組み込みコマンドを使用する

whileループなしでbashの読み取り組み込みコマンドを使用する

私は次のwhileループの組み込み関数に精通していますbashread

echo "0 1
      1 1
      1 2
      2 3" |\
while read A B; do
    echo $A + $B | bc;
done

make私はファイルを分割して中間結果を保存することが慎重になったいくつかのプロジェクトを進めてきました。したがって、単一の行を変数に分割することがよくあります。以下の例は正常に動作しますが、

head -n1 somefile | while read A B C D E FOO; do [... use vars here ...]; done

whileループは複数回実行されないため、これは少し愚かなことです。しかし、そうでない場合はwhile

head -n1 somefile | read A B C D E FOO; [... use vars here ...]

これを使用するときに読み取った変数は常に空です。read私は通常、多くの同様の行を処理するためにwhileループを使用するので、この動作を見たことがありません。 whileループなしで組み込みbash関数をどのように使用できますか?readそれとも、1行を複数の(!)変数として読み取る別の(より良い)方法がありますか?

結論として

答えは、これが範囲指定の問題であることを示しています。声明

 cmd0; cmd1; cmd2 | cmd3; cmd4

コマンドとして解釈され、cmd0同じスコープで実行されますが、コマンドとそれぞれにcmd1独自のサブシェルが提供されるため、スコープは異なります。元のシェルは、2つのサブシェルの親シェルです。cmd4cmd2cmd3

ベストアンサー1

変数を使う部分が新しい命令集合だからだ。代わりにこれを使用してください:

head somefile | { read A B C D E FOO; echo $A $B $C $D $E $FOO; }

この構文では、後ろにスペースを入れ、前に{ (セミコロン)を付ける必要があります。必ずしも必要ではありません。最初の行だけを読みます。;}-n1read

より良い理解のために、上記と同じことをするのに役立ちます。

read A B C D E FOO < <(head somefile); echo $A $B $C $D $E $FOO

編集する:

次の2つの声明は同じ効果を持つとよく言われます。

head somefile | read A B C D E FOO
read A B C D E FOO < <(head somefile)

まあ、まさにそうではありません。 1つ目headはからのbash組み込みパイプですread。あるプロセスの標準出力は別のプロセスの標準入力に移動されます。

2番目の説明は、リダイレクトとプロセスの交換です。bash独自に処理されます。 FIFO(パイプという名前<(...))を作成し、headその出力をFIFOに接続してからプロセスに<リダイレクトします。read

これまでは、これらが同じように見えます。ただし、変数を使用する場合はこれが重要です。まず、実行後の変数は設定されません。第二に、現在の環境で使用できます。

この状況では、各シェルは異なる動作をします。バラよりそのリンク彼らはこれのためにここにあります。コマンドのグループ化、プロセス置換()、またはここで文字列()を使用してbashこの動作を解決できます。{}< <()<<<

おすすめ記事