シェルコマンドを呼び出すときの一般的なawkバッファリングの問題

シェルコマンドを呼び出すときの一般的なawkバッファリングの問題

わずかな精度:

  • gawkではなく、一般的なawk
  • AIX 6.1以前のシェル:GNU bash、バージョン2.05b.0(1)

正しい順序で何かを表示しようとしているので、シェルの「sort」と「uniq」を介して出力をパイプしますが...作成した順序で出力を取得できません。

問題のあるコード:

egrep -i "something_FREQUENT" BIGFILE | sort | awk -F',' '
      { servs=servs $1 " " ; groupe=groupe "\n   " $2 ; }
  END { print "Groupes (alphabetical order):" ;
        printf groupe "\n" | "grep . | sort | uniq | xargs echo ";
        print ; rem="extra newline to help buffering... does NOT help.";
        system(""); rem="supposed to force flush of stdout... does NOT help.";
        print "Servers:"
        printf "%s\n", servs;
      } ' # if I add a final: "| cat" here (after "'"), does NOT help?... see last example

次のように出力されます。

Groupes (alphabetical order):

Servers:
( here a quite long list of severs... maybe until "buffer size" length? )
( etc.... but at some point :)(HERE_THE_groupe_OUTPUT)(rest of the servers here....)

??...恥ずかしいです。サーバーを表示する行の前に system(""); を追加しても役に立たないようです。

同じシステムのいくつかの関連テスト:

1)私のスクリプトに似ています。システムコールによる「長い」出力が壊れています。

prompt$:  yes "test1" | head -10 | awk '
         { all=all "\n" $0; }
     END { print "first line:"  ;
           printf all "\n" | "sort "; 
           system(""); 
           print "last line" ;
         }'

first line:
last line

test1
test1
test1
test1
test1
test1
test1
test1
test1
test1
  # notice: the order is mixed: the shell command output is last.

2)同じですが、今回は最後の「| cat'を追加します。魔法のように出力順序が変わります。しかし、上記のスクリプトで同じことをすることは役に立ちません。

prompt$:  yes "test2" | head -10 | awk '
         { all=all "\n" $0; }
     END { print "first line:"  ;
           printf all "\n" | "sort "; 
           system(""); 
           print "last line" ;
         }' | cat  # ONLY ADDITION: pipe awk through cat... this HELPS here (but NOT in my script!... ??)

first line:

test2
test2
test2
test2
test2
test2
test2
test2
test2
test2
last line
  # notice: the order is OK!

答え1

パイプをフラッシュするには、awk内でパイプを閉じる必要があります。 2番目の例では、次のようにします。

yes "test1" | head -10 | awk '
    { all=all "\n" $0; }
END { print "first line:"  ;
      printf all "\n" | "sort "; 
      close("sort ");
      print "last line" ;
    }'

最初の例でより明確にするには、次のようにします。

cmd = "grep . | sort | uniq | xargs echo ";
printf groupe "\n" | cmd;
close(cmd);

関連情報