다음과 같은 파일이 있습니다.
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 단계: 이 파일을 한 줄씩 읽고 스크립트를 통해 md5sum 및 줄 번호를 생성합니다.
이 두 단계의 문제점은 처리 시간이 더 많이 필요하고 파일 크기가 크다(~4GB)는 것입니다.
더 좋은 방법이 있나요?
답변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로 나누고 두 번째 단어 발생부터 시작하여 이전 형식의 행을 인쇄합니다Record
(두 번째는 처음 인쇄, 세 번째는 두 번째 인쇄) 시간 등).단어가 없는 줄 의 경우 변수
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