$ echo > 1 2 3; ls -latr 1; cat 1
-rw-rw-r-- 1 kahn kahn 4 Jun 23 14:05 1
2 3
これはリダイレクト評価に関連していますか>
?だから:
echo > 1 2 3
技術的には、次のように書き直すこともできます。
echo 2 3 > 1
?
IOリダイレクトの作業順序と評価方法をよりよく理解するのに役立つリソースはありますか?この例が役に立たないか一般的ではないかもしれないことは認めますが、ここで正確に何が起こっているのかをよりよく理解したいと思います。
答え1
参照できる適切なリソースはPOSIXです。シェル構文、単純なコマンドを次のように定義します。
simple_command : cmd_prefix cmd_word cmd_suffix | cmd_prefix cmd_word | cmd_prefix | cmd_name cmd_suffix | cmd_name ;
ここで最も関連性の高い部分は次の定義ですcommand_suffix
。
cmd_suffix : io_redirect | cmd_suffix io_redirect | WORD | cmd_suffix WORD ;
これは再帰的であるため、リダイレクトパラメータとコマンドパラメータは任意の順序で表示できます。
また、POSIX は以下を定義します。リダイレクト構文〜のように
[n]redir-op word
n
オプションの数字とリダイレクト演算子(>
あなたの場合)の間にスペースは使用できませんが、リダイレクト演算子と次の単語の間にスペースは使用できます。拡張されるとword
(1
あなたの場合)は、ストリームが配信される(またはソースから)ファイルの名前として使用されます。
したがって、文を書くのも合法だ。
$ echo > 1 foo bar
# ^^^^ ^^^^^^^^^^^^^
# \ \
# \ cmd_suffix
# \ ^^^ ^^^ ^^^
# \ \ \ \
# \ \ \ WORD
# \ \ WORD
# \ io_redirect
# cmd_name
または
$ echo foo >1 bar
でも
$ echo > 1 foo > 1 bar > 1
(もちろん繰り返しは> 1
何の意味もありません。)
完全性を期すために、定義cmd_prefix
自体simple_command
は再帰的に定義されます。
cmd_prefix : io_redirect | cmd_prefix io_redirect | ASSIGNMENT_WORD | cmd_prefix ASSIGNMENT_WORD ;
これは、リダイレクトと変数の割り当てが任意の順序でコマンドの前に表示されることを意味します。
たとえば、次のようにできます。
$ LC_ALL=C <infile sort >outfile 2>errfile
# ^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^
# \ \ \
# cmd_prefix cmd_word cmd_suffix
または
$ 2>errfile >outfile <infile LC_ALL=C sort
または
$ LC_ALL=C sort <infile 2>errfile >outfile
これらはすべて同じように有効ですが、リダイレクト、変数の割り当て、および拡張は左から右に行われ、順序が関連する可能性があることを覚えておく必要があります(infile
存在しない場合はoutfile
切り捨てられませんcat <infile >outfile
)cat >outfile <infile
。
答え2
単語はスペースで区切られます。引用符付き文字列は、スペースに関係なく単一の単語として扱われます。変数の値は、使用されるときのトークン化の候補です(これが通常、変数名を二重引用符で囲むのが最善の理由です"$var"
)。
リダイレクト演算子は、次の単一の単語を使用します。
詳細については、シェルのマニュアルページ(man bash
「拡張」の下など)で確認できます。
拡張順序は、中かっこ拡張、チルダ拡張、パラメータ、変数と算術拡張、コマンド置換(左から右へ)、トークン化、パス名拡張です。