Linuxスクリプトで「while read ...」を使用する


34

誰かが次のコードがどのように機能するか説明してもらえますか?

echo '1 2 3 4 5 6' | while read a b c
do
  echo $c $b $a
done

具体的には、私はこのループの出力がある理由を知りたいのですが3 4 5 6 2 1、代わりに3 2 16 5 4二つの別々の行に?心を包み込むことができないようです...

回答:


41

read標準入力から行全体を読み取り、行をフィールドに分割し、このフィールドを指定された変数に割り当てます。変数よりも多くのピースがある場合、残りのピースは最後の変数に割り当てられます。

あなたのケースがに$a割り当てられ1$b割り当てられている2$c残り3 4 5 6


フロリアンありがとう!今では理にかなっています...何らかの理由で、スペースが各変数の読み取りを区切ると考えましたが、明らかにそうではありません。私はあなたの助けに感謝します!!
linuxgringo

24

この方法でループを書き換えると、何が起こっているのかがわかります。

echo '1 2 3 4 5 6' | while read a b c
  do
    echo '(iteration beginning)' a="$a" b="$b" c="$c" '(iteration ending)'
  done

これにより、その出力として次の結果が得られます。

(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)

最初に、1つのエコーコマンドのみが実行されることに注意してください。複数回実行された場合、とりわけ、(iteration beginning)および(iteration ending)部分文字列が複数回印刷されるのを見るでしょう。

これは、whileここでループを作成しても、実際には何も達成されないということです。read組み込みは、空白で区切られたテキスト読み出し1をそれぞれ指定された変数に。追加の入力は、指定された最後の変数の最後に追加されます。2したがって、変数aおよびb値をとる12、それぞれは、一方cの値をとります3 4 5 6

ループ条件(while read a b c)が2回目に評価されると、パイプからの入力がなくなるため(1行のテキストのみをパイプ処理します)、readコマンドはtrueではなくfalseに評価され、ループは(実行する前に)停止しますボディをもう一度)。

1:技術的かつ具体的にするために、readbuiltinは、変数名を引数として渡すと、入力を読み取り、IFSの空白に遭遇したときにそれを個別の「単語」分割しますこの質問この記事参照)。

2read余分な入力フィールドを最後に指定された変数に詰め込む動作は、最初は多くのスクリプト作成者にとって直感的ではありません。Florian Dieschの答えが述べているようにread常に行全体を(試行して)読み、それreadがループありとなしの両方で使用できるようになっていると考えると理解しやすくなります。


エリア、すべての詳細を説明してくれてありがとう。私はその疑いがあるwhile。この例では、通常の目的を果たすませんでしたが、その後、readコマンド私投げた...どういうわけか、私のようにそれを解釈「しながら、read a b c偽ではありません、んecho ...」。それが実際にどのように機能したかを説明してくれてありがとう。昨日このコードに出くわし、それを理解するまでバグになることを知っていました... lol
linuxgringo

@linuxgringo実際には、ループ本体read a b c trueと評価されるたびに実行され、ループ条件(read a b c)は複数回実行されます。最初に真と評価されるビットのみ。2回目は、パイプから読み取るすべき多くの入力がありませんので、ファイルの終わりが原因と、検出されたread返すように虚偽を。(の出力の最後のセクションを参照してください。help readゼロ手段は、シェルスクリプトで、それを注意して、詳細については「終了ステータス」に、真とゼロ以外の手段で偽を。)あなたが入力の複数行をパイプした場合while read ...、ループ本体は、希望複数回実行されます。
エリアケイガン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.