forとwhileの入力リダイレクト

forとwhileの入力リダイレクト

ただ好奇心、

このコマンドの仕組み:

$ <file cat

しかし、次のいずれもありません。

$ <file for
bash: for: command not found...

$ <file while
bash: while: command not found...

なぜそんなことですか?

答え1

これPOSIX構文このように書かれています。コマンドは次のように定義されます。

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition

簡単なコマンドはどこにありますか?

simple_command   : cmd_prefix cmd_word cmd_suffix
                 [...]

どちらもcmd_prefix最終的にcmd_suffixリダイレクトを許可します。複合コマンドの場合、redirect_listこれを許可する先行コマンドなしで最後にのみ許可されます。

少し落ちる持つ例えば ​​Zsh はこれをよく受け入れます:

% > output for x in a b c ; do echo $x; done
% cat output 
a
b
c

しかし、これはZshと互換性がありません。なぜなら、標準シェルの先行リダイレクトにより、コマンドは通常のfor単純なコマンドとして解析されるからです。つまり、次のようになります。効果的なシェルは文字通り呼び出されるコマンドを見つけて実行しようとしますfor(5つの引数とstdoutリダイレクトを含む)。エラーが発生すると、以下が表示されます。

$ > output for x in a b c
bash: for: command not found

(具体的には、Bashでは入力行全体が最初に解析されるため、for-do-done最初の例の項目全体をBashに入力すると構文エラーのみが削除され、前の項目はdo実行されません。)for

推測する必要がある場合、この定義の根本的な理由は常にこのように動作しているため、標準でそのようにエンコードされたためだと予想します。

たとえ議論するこの分野の標準的な変更について。 (おそらく正しい心を持っている人のうち、実際にはシェルループではなく、コマンド> output for ...呼び出しの意味に依存する人はいないでしょう。)for

答え2

forコマンドではなく、whileループヘッダーを開始する予約語です。ループ全体に対してリダイレクトを使用できますが、リダイレクトは最後にする必要があります。

これは実際にいいえ働く:

<file for((i=0;i<3;i++)); do read line; echo "$line"; done

これする働く:

      for((i=0;i<3;i++)); do read line; echo "$line"; done <file

関連情報