whileコマンドの後に続くコマンドをループでどのように実行できますか?

whileコマンドの後に続くコマンドをループでどのように実行できますか?
  1. while <command>whileループ内の<command>各ループの実行は他のループとは独立していますか?
  2. 次の例では、whileループはreadファイル内のすべての行を1つずつ読み取ることができますが、whileループのないwhileは繰り返されるたびに read常にファイルの最初の行を読み取るのはなぜですか?

    whileループを使用せずにファイル内のすべての行を1つずつ読み取ることはできますかread

    $ cat /tmp/tt
    1 2 3 4 5
    6 7 8 9
    10 11
    
    $ cat /tmp/tt | while read tt; do echo $tt; done
    1 2 3 4 5
    6 7 8 9
    10 11
    
    $ cat /tmp/tt | read tt
    $ echo $tt
    1 2 3 4 5
    $ cat /tmp/tt | read tt
    $ echo $tt
    1 2 3 4 5
    

答え1

第1四半期

while <command>whileループ内の<command>各ループの実行は他のループとは独立していますか?

はい、<command>実行されたループのすべてのループで実行されますwhile

実行されるループの数は、他のループも入力を消費すると他のループの影響を受けますstdin。このreadコマンドはstdinから読み取られます(-u nlesオプションを使用しない限り)。いくつかの他の読み取りは同じ入力を消費する可能性があり、これは影響を与えます。最初 whileリングの形。

第2四半期

コードに大きなバグがあり、新しいコードです[1]

$ cat /tmp/tt | {  read tt; echo "$tt";   }
1 2 3 4 5
$ cat /tmp/tt | {  read tt; echo "$tt";   }
1 2 3 4 5

コマンドはcat常にファイルの先頭から始まります。
このreadコマンド(-d()内に他のオプションを設定せずに)は、最初の行を取得して次のように入力します。new line$'\n'出口(パイプを閉じる)

ループに読み込んだ内容があっても、whileまだ実行するコードがあります(while)。これにより、パイプが開いたままになります。コマンドから次の行を取得しますcat

$ cat /tmp/tt | while read tt; do echo $tt; done
1 2 3 4 5
6 7 8 9
10 11

[1]コード​​がきれいでなければなりません。確認して$ttみてください。unset tt; cat /tmp/tt |{ read tt; echo "$tt"; }

答え2

read2つの出力インスタンスを持つ2つのコマンドラインがある場合、catそれを使用する方法では最初の行のみを読み取ることができます。なぜなら、readSTDINの最初の行は常に同じ内容を持つからです。

catの出力を複数回読み取ると、読み取りに使用されたSTDINが元の開始行にリセットされないため、次の行が得られます。

$ cat /tmp/tt | ( read tt ; echo $tt )
1 2 3 4 5

$ cat /tmp/tt | ( read tt ; echo $tt ; read tt ; echo $tt )
1 2 3 4 5
6 7 8 9

$ cat /tmp/tt | ( read tt ; echo $tt ; read tt ; echo $tt ; read tt ; echo $tt )
1 2 3 4 5
6 7 8 9
10 11

簡単に言うと、「(A)read同じ入力(STDIN)で1回、2回、3回実行すると、1行目、2行目、3行目が得られます。(B)複数回実行しますが、毎回readリセットする場合は入力を入力します。readすると、同じ最初の行が複数回表示されます。」

追加情報:readインスタンス(パイプの左側)を「グループ化」して、サブシェルはパイプを開いたままにします。を使用すると、whileサブシェルはパイプを開いたままにします。したがって、read「最初の行」ではなく「次の行」が毎回読み取られます。

関連情報