次のファイルがあります。
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つのステップの問題は、より多くの処理時間を必要とし、ファイルサイズが大きい(〜4 GB)ということです。
もっと良い方法がありますか?
答え1
ほとんどはそうかもしれません
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
簡単なコード説明:
フィールド区切り記号(入力と出力)を次に変更します。
|
割り当て機能
md5
(ありがとうピエールオリビエバレセアイデアの場合)適切な入力ラインのmd5sumを計算します。 (より良い方法があるかもしれませんので、コメントをお願いします。)単語を含む行の場合は、
Record
必要なフィールドを変数に入れてカウンタを1で除算し、2番目の単語の発生から始めて、古い形式の行を印刷しますRecord
(2番目は最初の印刷、3番目は2番目の印刷)時間など)。単語のない行の場合は、変数
Record
に自分自身を追加し、カウンターに1を追加してください。line
c
完了したら、最後にフォーマットされた行を印刷します。 (最後の行はメモリに保存され、
Record
次の単語に出会いましたが、ファイルの終わりに達したときに印刷する必要があるためです。)
答え2
Costasの回答に基づいています。
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の説明を参照してください。スクリプトは、md5と改行を印刷するためにprintf
結果行の先頭のみを実行します(印刷ではなく、改行を入れる)。
system(echo $line | md5sum)
2) 走るawk -F"|" -f parse.awk myfile
3)結果をお楽しみください:
1111|1|cb36533781d8dd00011a85b0db9b87b3
2222|4|521331bb249e8a668afa2199fa8d289a
3333|6|6c2564464187094e9db3159d26ade2a5