大容量記録/短絡処理

大容量記録/短絡処理

区切り文字を含むレコードを含む大容量テキストファイル(300 MB)があります\n\n。各行は、数字(フィールドラベル/名前)で始まり、その後にタブ文字とフィールドの内容/値が続くフィールドです。

110    something from record 1, field 110
149    something else
111    any field could be repeatable
111    any number of times
120    another field

107    something from record 2, field 107
149    fields could be repeatable
149    a lot of times
149    I mean a LOT!
130    another field

107    something from record 3
149    something else

各レコードは100 KBを超えることはできません。

以下では、問題のある履歴(制限より大きい)を見つけることができます。このレコード/「段落」から行末を削除します。そして長さを調べる:

cat records.txt | awk ' /^$/ { print; } /./ { printf("%s ", $0); } ' | awk '{print length+1}' | sort -rn | grep -P "^\d{6,}$"

次のいずれかで、間違ったレコードを処理する方法を見つけようとします。

  • 制限より大きいレコードを削除します。
  • 既知の問題を持つ特定のタグ(上記の例では149)のすべてのエントリを削除します。 149フィールドで始まるすべての行を削除すると、制限を超えるレコードがないと想定できます。

おそらく、制限に合わせて特定のフィールド/タグを十分に削除するには、スクリプト全体が必要です。最後のエントリを最初に削除することをお勧めします。

これは古いライブラリファイル形式に関連しています。ISO 2709

ベストアンサー1

問題のある記録だけをスキップしたい場合:

awk 'BEGIN { ORS=RS="\n\n" } length <= 100*1000' file

これにより、100,000文字以下のすべてのレコードが印刷されます。

レコードが大きすぎる場合、特定の正の整数で始まるフィールドを削除するには、次の手順を実行します。

awk -v number=149 'BEGIN { ORS=RS="\n\n"; OFS=FS="\n" }
    length <= 100*1000 { print; next }
    {
        # This is a too long record.
        # Re-create it without any fields whose first tab-delimited
        # sub-field is the number in the variable number.

        # Split the record into an array of fields, a.
        nf = split($0,a)

        # Empty the record.
        $0 = ""

        # Go through the fields and add back the ones that we
        # want to the output record.
        for (i = 1; i <= nf; ++i) {
            split(a[i],b,"\t")
            if (b[1] != number) $(NF+1) = a[i]
        }

        # Print the output record.
        print
    }' file

以前と同様に、短いレコードが印刷されます。長いレコードは削除され、最初のタブで区切られたサブフィールドが数字number(ここではコマンドラインで149と指定されている)のすべてのフィールドが削除されます。

大規模なレコードの場合、不要なフィールドなしでレコードが再生成されます。内部ループはタブのフィールドを分割し、タブで区切られた最初のサブフィールドではなくフィールドを追加して出力レコードを再作成しますnumber

for (i = 1; i <= nf; ++i) {
    split(a[i],b,"\t")
    if (b[1] != number) $(NF+1) = a[i]
}

POSIX仕様は、awk複数文字の値を指定しない場合に発生する状況を公開するため(ほとんどの実装ではこれを正規表現として扱う)、厳密に一貫した実装の代わりにRS使用できます。これにより、データの複数の空行が空のレコードを分離しなくなります。RS=""; ORS="\n\n"ORS=RS="\n\n"awk

おすすめ記事