私はこのようなファイルを持っています:
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)次の内容のファイル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
簡単なコードの説明:
フィールドセパレータ(入力と出力)を|
に変更します
md5
関数を割り当てて(アイデアについては Pierre-Olivier Vares に感謝)、適切な入力行のmd5sumを計算します。 (それを行うためのより良い方法があるかもしれません-あなたはコメントを歓迎します)
Record
Wordがある行の場合、必要なフィールドを変数に入れ、カウンターを1に分割し、Record
Wordの2回目の出現から始まる前のフォーマット済み行を印刷します(2回目の印刷の場合は1回目、3回目の印刷の場合は2回目など)オン)。
Record
Wordがない行の場合は、line
変数に自分自身を追加し、カウンターc
に1を追加します。
終了時に最後にフォーマットされた行を印刷します(最後の行はメモリに保存され、次のRecord
Wordに到達するが、ファイルの終わりに到達したときに印刷する必要があるため)