誰かが次のコードがどのように機能するか説明してもらえますか?
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 1
と6 5 4
二つの別々の行に?心を包み込むことができないようです...
誰かが次のコードがどのように機能するか説明してもらえますか?
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 1
と6 5 4
二つの別々の行に?心を包み込むことができないようです...
回答:
read
標準入力から行全体を読み取り、行をフィールドに分割し、このフィールドを指定された変数に割り当てます。変数よりも多くのピースがある場合、残りのピースは最後の変数に割り当てられます。
あなたのケースがに$a
割り当てられ1
、$b
割り当てられている2
と$c
残り3 4 5 6
。
この方法でループを書き換えると、何が起こっているのかがわかります。
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
値をとる1
と2
、それぞれは、一方c
の値をとります3 4 5 6
。
ループ条件(while read a b c
)が2回目に評価されると、パイプからの入力がなくなるため(1行のテキストのみをパイプ処理します)、read
コマンドはtrueではなくfalseに評価され、ループは(実行する前に)停止しますボディをもう一度)。
1:技術的かつ具体的にするために、read
builtinは、変数名を引数として渡すと、入力を読み取り、IFSの空白に遭遇したときにそれを個別の「単語」に分割します(この質問とこの記事も参照)。
2:read
余分な入力フィールドを最後に指定された変数に詰め込む動作は、最初は多くのスクリプト作成者にとって直感的ではありません。Florian Dieschの答えが述べているように、read
常に行全体を(試行して)読み、それread
がループありとなしの両方で使用できるようになっていると考えると理解しやすくなります。
while
。この例では、通常の目的を果たすませんでしたが、その後、read
コマンド私投げた...どういうわけか、私のようにそれを解釈「しながら、read a b c
偽ではありません、んecho ...
」。それが実際にどのように機能したかを説明してくれてありがとう。昨日このコードに出くわし、それを理解するまでバグになることを知っていました... lol
read a b c
trueと評価されるたびに実行され、ループ条件(read a b c
)は複数回実行されます。最初に真と評価されるビットのみ。2回目は、パイプから読み取るすべき多くの入力がありませんので、ファイルの終わりが原因と、検出されたread
返すように虚偽を。(の出力の最後のセクションを参照してください。help read
ゼロ手段は、シェルスクリプトで、それを注意して、詳細については「終了ステータス」に、真とゼロ以外の手段で偽を。)あなたが入力の複数行をパイプした場合while read ...
、ループ本体は、希望複数回実行されます。