web-dev-qa-db-ja.com

ファイルを読み取り、すべてのオカレンスを見つけて、オカレンス間のコンテンツのハッシュを生成します

私はこのようなファイルを持っています:

1   Record|1111|ABC
2   text in between for record 1
3   text in between for record 1
4   Record|2222|XYZ
5   text in between for record 2    
6   Record|3333|XYZ
7   text in between for record 3
8   .

このファイルを読んで、次のようなものを生成したい

<Record_number> | <start line> | <number of lines> | md5sum(content)

あれは:

1111|1|2|md5sum(Record|1111|ABC\ntext in between for record 1\ntext in between for record 1)
2222|4|1|md5sum(Record|2222|XYZ\ntext in between for record 2\n)

等.

現在、私は2段階のプロセスを使用してこれを行っています。

ステップ1:

grep -n -C 0 "Record|" ../test.txt | awk -F[':|'] '{print $3"|"$1}'

作成します

1111|1
2222|4
3333|6

ステップ2:このファイルを1行ずつ読み取り、スクリプトを使用してmd5sumと行数を生成します。

この2段階の処理では処理時間が長くなり、ファイルサイズが非常に大きくなる(約4GB)という問題があります。

これを行うためのより良い方法はありますか?

1
Sinoop Joy

コスタスの答えに基づいています。

1)次の内容のファイルparse.awkを作成します。

_/^Record/ {
  if (s>0) {
    printf ("%s|%s|", r,l)
    system("echo '"line"' | md5sum - | awk '{print $1}' ");
  }
  s=1;
  r=$2;
  c=1;
  l=NR;
  line="$0";
}
!/^Record/ {
  line=line"\n""$0";
  c+=1
}
END {
  printf ("%s|%s|", r,l)
  system("echo '"line"' | md5sum - | awk '{print $1}' ");
}
_

Costasの説明を参照してください。このスクリプトは、結果の行の先頭をprintf(改行ではなく)system(echo $line | md5sum)して、md5-と改行を出力します。

2)_awk -F"|" -f parse.awk myfile_を実行します

3)結果をお楽しみください:

_1111|1|cb36533781d8dd00011a85b0db9b87b3
2222|4|521331bb249e8a668afa2199fa8d289a
3333|6|6c2564464187094e9db3159d26ade2a5
_

ほとんどの場合、

awk -F"|" -v OFS="|" '
function md5(lines){
  func="printf \"%s\" \""lines"\"|md5sum|cut -f1 -d\ " ;
  func | getline v;
  return v
}
/Record/{
  if(s>0)
    print r,l,c,md5(line);
  s=1;
  r=$2;
  c=1;
  l=NR;
  line=$0
}
!/Record/{
  line=line"\n"$0;
  c+=1
}
END{
  print r,l,c,md5(line);
}' file

簡単なコードの説明:

  1. フィールドセパレータ(入力と出力)を|に変更します

  2. md5関数を割り当てて(アイデアについては Pierre-Olivier Vares に感謝)、適切な入力行のmd5sumを計算します。 (それを行うためのより良い方法があるかもしれません-あなたはコメントを歓迎します)

  3. Record Wordがある行の場合、必要なフィールドを変数に入れ、カウンターを1に分割し、Record Wordの2回目の出現から始まる前のフォーマット済み行を印刷します(2回目の印刷の場合は1回目、3回目の印刷の場合は2回目など)オン)。

  4. Record Wordがない行の場合は、line変数に自分自身を追加し、カウンターcに1を追加します。

  5. 終了時に最後にフォーマットされた行を印刷します(最後の行はメモリに保存され、次のRecord Wordに到達するが、ファイルの終わりに到達したときに印刷する必要があるため)

1
Costas