複合コマンドに使用されるコマンドリダイレクトの提供

複合コマンドに使用されるコマンドリダイレクトの提供

< myfileコマンドで入力または出力(、または)の> myfileリダイレクトを提供するには、test-commandsconsequent-commandscommand1command2

if test-commands; then
consequent-commands;

until test-commands; do consequent-commands; done

while test-commands; do consequent-commands; done

command1 && command2

command1 || command2

リダイレクトはどこに配置する必要がありますか?

たとえば、私は見る

while read a; 
  do echo "$a"; 
done < myfile;

< myfileなぜ裏側doneではなく裏側なのか気になりますread a

また(この記事の最初の段落のように)もっと広く考えることになりました。

  • 複合コマンドに表示されるコマンドはどこに配置する必要がありますか?

  • リダイレクトが出力か入力かは重要ですか?

  • 複合コマンドの最後にリダイレクトを入れると、リダイレクトが適用される複合コマンド内のどのコンポーネントコマンドをどのように知ることができますか?

ありがとうございます。

答え1

単純なコマンド内のどこにでもリダイレクトを配置できます(エイリアス、関数、組み込み関数、または引数を使用して実行可能ファイルを呼び出すなど)。一方、複合コマンドにリダイレクトを適用するには、後でリダイレクトする必要があります。これがシェル構文が設計された方法です。たとえば、次は同じです。

<myinput mycommand argument
mycommand <myinput argument
mycommand argument <myinput

リダイレクトを移動できません。

while …; do …; done <myinput
{ command1; command2; } <myinput

複合コマンドがキーワードまたは句読点で終わる場合にのみ、リダイレクトを適用できます。または、同じアイテムにリダイレクトを適用するには、foo && bar次のように中括弧内にコマンドを入れます。foo; barfoo | bar

{ foo && bar; } <myinput

スクリプト

while read a; do
  echo "$a"
done <myfile

そして

while read a <myfile; do
  echo "$a"
done

どちらも構文的に正確ですが、2番目のものは役に立つことはありません。コマンドのリダイレクト演算子は、次のことを意味します。

  1. 指定されたファイルを開きます。
  2. 指定されたファイルを必要なファイル記述子に追加します(たとえば、0はを意味します<)。
  3. コマンドを実行します。
  4. ファイル記述子を閉じます。

したがってread a <myfile、繰り返すたびにファイルが再び開きます。つまり、最初の行を永遠に読みます。

読み込み中にループを使用し、ループ本体の周囲の標準入力を保持するには、別のファイル記述子から読みます。

while read a <&3; do
  # commands that can use stdin
done 3<myfile

リダイレクト演算子は<&3ファイル記述子のコピーのみを実行し、「ファイルを再開しません」。上記の列挙にはステップ1はありません。

答え2

単純なコマンドの場合、リダイレクト位置決めは同じ行にあり、どこにでも柔軟です;

command1 arg <file
<file command1 arg
command1 <file arg

スタイル的には通常、最初の形式が好ましい。

パイプまたは条件を介してリンクされたコマンドの場合、リダイレクトはリンクされたコマンドと同じ側になければなりません。最初のコマンドが入力を受け取る必要がある場合は、次のことを行う必要があります。

command1 <file || command2

command2 が入力を受け取るには、次のようにします。

command1 || command2 <file

while他のブロック複合コマンドの場合、リダイレクトをfor最後に配置する必要性は単に構文論的な現実です。

<file { command1 || command2; } # error
{ command1 || command2; } <file  # okay

たとえば、複合コマンドはこのコンテキストで単一のコマンドとして機能するため、リダイレクトされた入力はcommand2をターゲットにしてcommand1を除外できません。

もちろん、配管がオプションの場合もあるので、上記の2番目の例は次のとおりです。

cat file | { command1 || command2; }

whileループの場合:

cat myfile | while read a; do ...

これらの例ではすべて入力を使用していますが、出力にも同様に適用されます。注意すべき点は、入力と出力の両方を使用する場合、または他のマルチリダイレクト構成を使用する場合です。リダイレクトは左から右に処理されます。

もっと読む内容は次のとおりです。

http://wiki.bash-hackers.org/syntax/redirection

http://wiki.bash-hackers.org/howto/redirection_tutorial

関連情報