ただ好奇心、
このコマンドの仕組み:
$ <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