awkのprint / printf出力をシェルコマンドにパイプして、そのステートメントが関連していない他のすべてのprint / printfステートメントの後に実行されるようにします。

awkのprint / printf出力をシェルコマンドにパイプして、そのステートメントが関連していない他のすべてのprint / printfステートメントの後に実行されるようにします。

このawkスクリプトが与えられたら:

END  {
print "Y" | "cat" 

print "X"
print "X"
}

# Output: 
# X
# X
# Y

Yは他のステートメントよりも先に実行する必要があるので、Yを最初に印刷するのはどうですか?

答え1

cat■前にプロセスを終了してY印刷するには、sの後に呼び出すだけXです。close("cat")print "Y" | "cat"

残りの部分はマンページに記載されているので、読むことをお勧めします。

Yは他のステートメントよりも先に実行する必要があるので、Yを最初に印刷するのはどうですか?

catその出力は、他のステートメントの前に作成または終了しないでください。呼び出し前、呼び出し後、または呼び出しの間に出力を書き込むことができますprint "X"

print ... | "command ..."awkでこのようなものを使用すると、標準command ..入力はパイプに接続された非同期プロセスで始まり(を通じて popen("command ...", "w"))プロセスは必ずしも終了せず、出力を呼び出して書き込む前にclose("command ...")(またはawkが式を終了するときに暗黙的に)完全です。

次の例をご覧ください。

BEGIN {
   print "foo" | "cat > file"
   print "bar" | "cat > file"
}

結果にはfile2行が含まれ、fooコマンドbarcat > file各行に対して個別に実行されません。

答え2

awkのリダイレクトとパイプはshのリダイレクトとパイプに似ていますが、大きな違いが1つあります。 sh は、foo >barコマンドの実行中にのみオープン状態を維持し、待機して終了します。 awkでは、リダイレクトまたはパイプは明示的に閉じられるまで開いたままになり、同じファイル名またはコマンドに対する複数のリダイレクトまたはパイプは開いたリダイレクト/パイプを再利用します。barfoofoo | barfoobar

たとえば、shでは、各ソートコマンドが2行の入力のみを取得するため、、、、がa印刷bされます。cab

{ echo b; echo a; } | sort
echo c
{ echo b; echo a; } | sort

ただし、awkでは、、、、、cを出力します(awkの出力がラインバッファであると仮定し、それ以外の場合は遅延aする可能性があります)。これは、コマンドが1つだけで、すべての入力データが取得されるまで何も印刷されないためです。パイプの入力側が閉じている場合にのみ発生します。abbcsort

{ print "b"; print "a"; } | "sort";
print "c";
{ print "b"; print "a"; } | "sort";

パイプコマンドを終了するには、closeこの関数を明示的に呼び出します。 Awkは、終了時に開いているすべてのパイプとリダイレクトを暗黙的に閉じます。これによりa、、、、、bが印刷されます。cab

{ print "b"; print "a"; } | "sort"; close("sort");
print "c";
{ print "b"; print "a"; } | "sort"; close("sort");

foo繰り返しますが、このawkフラグメントは、1行目が1回開かれ、2行目が実行されたときに開かれるため、2行のファイルを生成します。

print "hello" >"foo";
print "world" >"foo";

そして、このshフラグメントは、2行目が最初の行で生成されたファイルを開き、書き込み前に切り捨てられるため、単一行ファイルを生成しますworld

echo hello >foo
echo world >foo

awkがこのように設計された主な理由は、各処理ラインに暗黙のループがあるためです。 sh でループの行を処理するには、通常、ループの周りにリダイレクトを作成します。

while read line; do
  if condition "$line"; then
    process line
  fi
done >output

ただし、awkでは暗黙的なループにリダイレクトを適用できないため、次のように書きます。

condition($0) { process $0 >"output" }

awk方式はループや他のブロックの途中でもパイプを自由に開閉できるので、より強力です。 shでは、リダイレクトに組み込みコマンドを使用できますが、execパイプは使用できません。パイプは(複合である可能性がある)コマンドに完全に適用する必要があります。

関連情報