일부 프로세스의 로그가 포함된 대용량 파일이 있습니다. 로그에는 "REQUEST(항상)/RESPONSE(때때로)"와 같은 줄이 포함되어 있지만 RESPONSE가 반드시 REQUEST 다음 줄인 것은 아닙니다. RESPONSE가 나타나기 전에 REQUEST 헤더가 여러 번 나타날 수 있습니다. 존재하는 경우 요청과 응답에 참여하고 해당 행을 인쇄하고 싶습니다. 이것이 지금까지 시도한 것이지만 출력에 일부 줄이 누락되었습니다.
awk 'BEGIN {filename = "log1.etb"}
{line_num++; print "FNR: " FNR " NR: " NR " Counter: " line_num;
if ($0 ~ /REQUEST.*RPCLIB/)
{seqid = $0; sub(/^.*@SeqID/,"SeqID",seqid);
line_req = $0; line_resp = ""; ref_resp = 0;
ref_req = line_num; tot_req++;
print "REQUEST: " $0;
for(i=1;i<=line_num+99999;i++1) {getline < "log.etb"; if ($0 ~ /RESPONSE/ && $0 ~ seqid) {ref_resp = +i; line_resp = $0; break;}};
print "FNR: " FNR " NR: " NR " REQUEST: " ref_req " RESPONSE: " ref_resp " " seqid;
print line_req"+"line_resp > filename;
FNR = line_num-1; NR = FNR;
}
}
END {print "Total REQUEST: " tot_req}
' ../EXX/log.etb
입력하다:
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9517
RESPONSE 2019-01-16 00:32:07.809@{fields}@SeqID = 9517 , Partner SeqID = 3393
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9515
REQUEST 2019-01-16 00:32:07.810@{fields}@SeqID = 9520
RESPONSE 2019-01-16 00:32:07.810@{fields}@SeqID = 9520 , Partner SeqID = 3395
원하는 출력:
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9517+W02/RESPONSE 2019-01-16 00:32:07.809@{fields}@SeqID = 9517 , Partner SeqID = 3393
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9515+
REQUEST 2019-01-16 00:32:07.810@{fields}@SeqID = 9520+W02/RESPONSE 2019-01-16 00:32:07.810@{fields}@SeqID = 9520 , Partner SeqID = 3395
요청/응답에 연결된 SeqID 번호이지만 어느 시점에서 로그에 다시 나타날 수 있습니다. 또한 REQUEST는 RESPONSE 이전에 여러 번 발생할 수 있으며 RESPONSE는 발생할 수도 있고 발생하지 않을 수도 있습니다.
답변1
댓글을 달 수가 없어서 답변으로 댓글을 남깁니다. 죄송합니다.
SEQID가 일치하면 REQUEST와 RESPONSE에 참여하고 싶습니까? 먼저 seqid를 기준으로 데이터를 정렬하면 어떨까요? 응답이 항상 요청을 따르도록 보장합니다.
답변2
나는 당신을 도울 수 없지만 awk
그렇게 하기 위해 이 Bash 스크립트를 만들었습니다.
최소한 Bash v4가 필요합니다., 하지만 이는 매우 일반적이어야 합니다..
stdin의 입력이 필요합니다. 즉, 다음과 같이 호출해야 합니다.
cat logfile | script.sh
또는:
script.sh < logfile
나는 그것이 바람직할 것이라고 생각하여 의도적으로 이렇게 했지만 파일 이름을 스크립트에 포함시키는 것은 쉽습니다. 그냥 명령 cat -n
의 |
.
다음을 처리합니다.
- 답장 없음
- 해당 ID를 사용하여 찾은 최신 요청에 응답을 추가하여 요청을 반복합니다.
- @ 기호 다음에 SeqID 필드를 허용합니다(첫 번째 명령
sed
의 정규식을 살펴보세요.) - REQUEST 및 RESPONSE 리터럴 정규식을 레코드 구별 기준으로 사용합니다(
if-elif-else-fi
코드 블록 보기) - 일치하는 req/resp 쌍 연결
+
화타이
#!/bin/bash
declare -A reqs=()
{
while IFS= read -r line ; do
read -r seqid rest <<<"${line}"
line="${line#${seqid} }"
if [[ "${line}" =~ REQUEST ]] ; then
[ "${reqs[$seqid]}" ] && printf '%s+\n' "${reqs[$seqid]}"
reqs[$seqid]="${line}"
elif [[ "${line}" =~ RESPONSE ]] && [ "${reqs[$seqid]}" ] ; then
printf '%s+%s\n' "${reqs[$seqid]}" "${line}"
unset reqs[$seqid]
else
printf 'strange record at line no. %s\n' "${line}" >&2
fi
done < <(cat -n | sed -e 's/\(.*@\)SeqID *= *\([0-9]\+\)\(.*\)/\2 &/') ;
printf '%s+\n' "${reqs[@]}" ;
} | sort -k 1 | sed -e 's/\(^\|+\)[[:blank:]]\+[0-9]\+[[:blank:]]\+/\1/g'
답변3
다음을 시도했는데 훌륭하게 작동합니다.
for i in `cat k.txt| awk -F "=" '{print $2}'| awk -F "," '{print $1}'| sed -r "s/\s+//g"| sort| uniq`; do sed -n '/'$i'/p' k.txt|sed '1s/$/\+/g'| sed "N;s/\n/W02\//g";done
산출
for i in `cat k.txt| awk -F "=" '{print $2}'| awk -F "," '{print $1}'| sed -r "s/\s+//g"| sort| uniq`; do sed -n '/'$i'/p' k.txt|sed '1s/$/\+/g'| sed "N;s/\n/W02\//g";done
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9515+
REQUEST 2019-01-16 00:32:07.809@{fields}@SeqID = 9517+W02/RESPONSE 2019-01-16 00:32:07.809@{fields}@SeqID = 9517 , Partner SeqID = 3393
REQUEST 2019-01-16 00:32:07.810@{fields}@SeqID = 9520+W02/RESPONSE 2019-01-16 00:32:07.810@{fields}@SeqID = 9520 , Partner SeqID = 3395
praveen@praveen:~$
답변4
다음 코드를 시도했지만 대용량 파일에서는 시간이 너무 오래 걸립니다.
awk '{
if ($0 ~ /REQUEST/ && $0 ~ /RPCLIB/)
{seqid = $0; sub(/^.*@SeqID/,"SeqID",seqid);
line_req = $0; line_resp = "";
rng_s = NR; rng_e = NR + 99999;
cmd = "awk '\''/RESPONSE.*" seqid "/ && NR >= " rng_s " && NR <= " rng_e " {print $0;exit}'\'' logfile"
cmd | getline line_resp;
close(cmd);
print line_req"+"line_resp;
}
}
' logfile