この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"
}
結果にはfile
2行が含まれ、foo
コマンドbar
はcat > file
各行に対して個別に実行されません。
答え2
awkのリダイレクトとパイプはshのリダイレクトとパイプに似ていますが、大きな違いが1つあります。 sh は、foo >bar
コマンドの実行中にのみオープン状態を維持し、待機して終了します。 awkでは、リダイレクトまたはパイプは明示的に閉じられるまで開いたままになり、同じファイル名またはコマンドに対する複数のリダイレクトまたはパイプは開いたリダイレクト/パイプを再利用します。bar
foo
foo | bar
foo
bar
たとえば、shでは、各ソートコマンドが2行の入力のみを取得するため、、、、がa
印刷b
されます。c
a
b
{ echo b; echo a; } | sort
echo c
{ echo b; echo a; } | sort
ただし、awkでは、、、、、c
を出力します(awkの出力がラインバッファであると仮定し、それ以外の場合は遅延a
する可能性があります)。これは、コマンドが1つだけで、すべての入力データが取得されるまで何も印刷されないためです。パイプの入力側が閉じている場合にのみ発生します。a
b
b
c
sort
{ print "b"; print "a"; } | "sort";
print "c";
{ print "b"; print "a"; } | "sort";
パイプコマンドを終了するには、close
この関数を明示的に呼び出します。 Awkは、終了時に開いているすべてのパイプとリダイレクトを暗黙的に閉じます。これによりa
、、、、、b
が印刷されます。c
a
b
{ 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
パイプは使用できません。パイプは(複合である可能性がある)コマンドに完全に適用する必要があります。