awkのコプロセスと双方向パイプ

awkのコプロセスと双方向パイプ

command | getline varの違いを理解しようとしていますcommand |& getline var。通常どれを使うべきですか?コプロセスと双方向パイプについて読みましたが、状況が本当に混乱しているので説明が必要です。

実は私が使っているのは

kmd=sprintf("%s%d\n", "tput bold; tput setaf ", knum)
tseq[knam] = ( (kmd | getline outp) > 0 ? outp : "<" knam ">" )
close(kmd)

ここでの共同プロセスは何ですか? tputを使用していますか?コードには一方向パイプ通信しかないと思います。これを使用すると、どのような利点がkmd |& getline outpあり、後者を使用する必要がありますか?

答え1

あなたの質問のコードには補助プロセスはありません。呼び出すサブシェルを作成してから、tputそのサブシェルの出力を読み取るだけですgetline

情報What would be the benefit of using kmd |& getline outp, and should I use the latter instead?- 役に立たないだけでなく、これは構文の半分にすぎないため、次のことが必要です(エラー処理を含む)。

print knum |& kcmd
kcmd |& getline outp
close(kcmd)

しかし、これはstdinを読み込み、stdoutを生成するコマンドが含まれている場合にのみ意味があります。kcmd下痢 そうしても、やりたいことに何の役にも立たず、コードが不要になります。鈍い人。

以下は、コルーチンが有用な場合の例です。パイプを介して着信数値ストリームを並べ替えてから、sort数字を印刷する前に数字で操作を実行します。

$ cat tst.awk
BEGIN {
    cmd = "sort -rn"
}
{ print |& cmd }
END {
    close(cmd, "to")
    while ( (cmd |& getline line) > 0 ) {
        print line, line / NR
    }
    close(cmd)
}

$ seq 5 | awk -f tst.awk
5 1
4 0.8
3 0.6
2 0.4
1 0.2

デフォルトでは、一時ファイルに書き込む必要があるawkスクリプトを作成する場合は、そのファイルに対して外部コマンドを呼び出してから、そのコマンドの出力をスクリプトに戻します。ここでは、コプロセッシングの使用を検討する必要があります。一時ファイルを作成する必要がないので本当です。

詳細については、Arnold RobbinsのEffective AWKプログラミング5版の本をダウンロードして、他のプロセスとの双方向通信セクションを読んでください。

答え2

いいえ、引き続き単純な「|」を使用する必要があります。あなたの仕事が以下の場合:いくつかのデータを外部ツールに提供し、ツールによって提供される結果を使用してください。これは簡単な一方向パイプで十分です。

双方向パイプは、次の場合にのみ必要です。

  • 自分のプロセスが存続している間、外部ツールの同じインスタンスをメモリに保持しようとしています。
  • 外部ツールに送信されるデータは論理的にパケットで区切られます。
  • 次のパケットを送信する前に、1つのパケットを処理した結果を受け取る必要があります。
  • 前のパケットの結果に基づいて、次のパケットを調整する必要があります。

これら4つの質問の1つが「いいえ」の場合、双方向パイプは必要ありません。

双方向パイプを使用する実際のケースを作成することは困難です。おそらく、いくつかのデータベースクエリツールやWebアプリケーションで使用するために発明されたでしょう。ただし、ほとんどの場合、ある種のサーバーを使用する必要がある場合、これらの操作は通常、シェルなどの言語でもperl解決できますpythonawk通常、テキスト処理専用に予約されています。

非現実的ですが、技術的に正しい例は次のとおりです。

#!/bin/gawk
BEGIN {
  tool="bc"

  print "2+3" |& tool
  tool |& getline res

  if (res>4)
     print "5+6" |& tool
  else 
     print "10+45" |& tool
  tool |& getline res

  close(tool, "to")

  print res
}

ここに示すように、最初の印刷では、「クエリ」を外部ツール(bcこの場合は単純な電卓)に送信します。次に、最初のクエリの結果に基づいて別のクエリを送信し、最後に結果を印刷します。両方のクエリを処理するツールの同じインスタンスです。最初からprint "2+3" |& command特別声明まで公開されますclose(command, "to")

関連情報