単一プロセスを使用すると、AWKプロセスは1つの巨大なファイルセットになります。

単一プロセスを使用すると、AWKプロセスは1つの巨大なファイルセットになります。

AWK一連の変数がファイルに蓄積されるように、大容量ファイルの大きなサブセットを処理するには(*)を使用する必要があります。

AWKファイルワイルドカードを使用して複数のファイル名を渡す簡単な方法は、小さなファイルセットには適していますが、本番規模の"Argument list too long"ファイルセットとして実行すると予想される結果が得られます。

この種の問題を解決するためのベストプラクティスは何ですか?


いくつかの詳細:

  • フルセットは20-50Kファイルです。現在、単一の実行のサブセットは5-10Kです(ただし、簡単に拡張できれば良いでしょう)。

  • ファイルセット内の各単語の発生回数を数えて、各ファイルにランタイム定義の重みを付与する必要があります。同じファイル内の各単語は同じ重みを持ちますが、異なるファイルに現れる同じ単語は異なる重みを持ちます。次に、各単語の文書重量を追加します。

  • したがって、ファイルセットをより小さなサブセットに分割することは、中間結果を集計することを意味します。非常にエレガントに見えず、複数の中間ファイルを結合するときに浮動小数点を追加する必要があるため、プロセス全体の読みやすさと直感性が低下します。

  • 私が考えることができるもう一つの方法は、awk&の出力を提供することです。私が嫌いなのは、/の読みやすさを犠牲にしてファイルごとの重み、カウンタ、および配列をリセットするために、ファイル間の特定の区切り文字を解析することです。findcatBEGINFILEENDFILE

  • 現在のフォルダで処理されるファイルのサブセットは別々のファイルとして提供されます。 A.BEGINFILE不要なファイルは私のセクションからスキップします。

  • 各文書の重量
  • ファイル間集計手段におけるファイル重み計算の分離二つ読み取りが数十GBを超えています。これを防止したい。

(*) またはAWKこの種の処理に最適なツールではない可能性があります。それでは、どの代替案をお勧めしますか?

ベストアンサー1

パラメータが多すぎる場合は、ファイルを直接開いて処理する必要があります。 awkを使用すると、拡張機能を使用せずに次のものを使用できます(Jeffの答えと同じアイデア)。

awk '{ filename = $0; while(getline < filename > 0) { print $0; }}'

たとえば、find次のコマンドを組み合わせて必要なファイルを見つけます。

find /etc/ -maxdepth 1 -type f -perm -444 -size 1 | \
  awk '{ filename = $0; while(getline < filename > 0) { print filename ":" $0; }}'

また、awkのバージョンに応じて、処理のためのより多くのファイルをプッシュすることができます。ここに文書化されているように

プログラムはARGCとARGVの要素を変更することができます。 awkが入力ファイルの終わりに達するたびに、ARGVの次の要素を次の入力ファイルの名前として使用します。プログラムは、別の文字列を保存して読み取るファイルを変更できます。標準入力を表すには「-」を使用します。追加の要素を保存してARGCを増やすと、追加のファイルを読み取ることができます。

例を使って説明します。

find /etc/ -maxdepth 1 -type f -perm -444 -size 1 | \
  awk '
    # When reading from STDIN, assume it is a list of files to read
    FILENAME == "-" { ARGV[ARGC] = $0; ARGC += 1 }
    # When not reading STDIN, it is a file to process
    FILENAME != "-" { print "---", FILENAME ":" FNR ":" $0; }
    # These will run after every file, including STDIN, hence the check
    BEGINFILE { if (FILENAME != "-") { print ">>>", FILENAME; } }
    ENDFILE   { if (FILENAME != "-") { print "<<<", FILENAME, FNR, "lines"; } }'

おすすめ記事