로그 파일을 구문 분석하고 중요한 메시지가 발견되면 이메일을 보내는 ksh 스크립트를 작성 중입니다. 일부 메시지는 정보 제공용이므로 무시하고 싶습니다.
로그 파일의 형식은 다음과 같습니다.
2018-01-24.08.24.35.875675 some text
more text
more text
more text
more text
2018-01-24.08.24.37.164538 some text
more text
more text
INF9999W <-- informational text
more text
2018-01-24.08.24.46.8602545 some text
more text
more text
more text
타임스탬프는 메시지 구분 기호로 처리되며 타임스탬프는 그 뒤의 메시지에 속합니다. "메시지 텍스트"가 나타날 때마다 파일을 검색한 다음 파일에서 전체 메시지를 삭제하고 싶습니다(이전 타임스탬프부터 다음 타임스탬프 직전까지).
다음을 사용하여 해당 줄을 삭제할 수 있도록 이전 및 다음 타임스탬프의 줄 번호를 쉽게 확인하려면 어떻게 해야 합니까?
awk 'NR<'$preceding_ts' || NR >='$following_ts'
내 접근 방식은 모든 타임스탬프 줄을 파일에 넣은 다음 "정보 텍스트" 줄 # 앞뒤의 타임스탬프 줄을 찾을 때까지 파일을 반복하는 것이었습니다. 특히 대용량 파일을 작업할 때 작업량이 많은 것 같습니다. 더 효율적인 방법이 있습니까?
integer inf_line
integer last_ts_line
integer cur_ts
cp $error_log $copy_log
while true
do
inf_line=$(grep -n "INF99999W" $copy_log | head -1 | cut -f1 -d":")
if [[ $inf_line -eq 0 ]]
then
break
fi
grep -n -E "^20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]-" $copy_log | cut -f1 -d":" > $ts_lines
last_ts_line=99999999
cat $ts_lines | while read cur_ts
do
if [[ $cur_ts -gt $inf_line && $last_ts_line -lt $inf_line ]]
then
awk 'NR<'$last_ts_line' || NR >='$cur_ts'' $copy_log > $temp_log
cp $temp_log $copy_log
last_ts_line=$cur_ts
break
fi
last_ts_line=$cur_ts
done
if [[ $last_ts_line -lt $inf_line ]]
then
awk 'NR<'$last_ts_line'' $copy_log > $temp_log
cp $temp_log $copy_log
fi
done
감사해요.
답변1
현재 메시지의 행을 저장하여 구현하고 메시지가 끝날 때 INF
표시가 없으면 저장된 배치를 인쇄합니다. 여기서 d
현재 메시지(d는 데이터를 나타냄)를 보유하는 행은 p
저장된 행을 인쇄할지 여부를 알려줍니다.
awk -vinfo='INF99+' \
'/^20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]/ {
if (p) printf "%s", d; d = $0 ORS; p=1; next }
$0 ~ info {p=0}
{d = d $0 ORS}
END {if (p) printf "%s", d}' < log
여기의 첫 번째 규칙은 타임스탬프 행과 일치하고 true인 경우 저장된 행을 인쇄하고 해당 행을 저장한 후 1로 p
설정합니다 . 두 번째 규칙은 p
해당 패턴이 있는 줄이 보이면 0으로 재설정됩니다. 패턴이 변수로 설정됩니다 . 세 번째 규칙은 현재 행을 수집된 행에 추가하고, 다시 이 규칙은 설정된 경우 수집된 행만 인쇄합니다 .p
info
-vinfo=...
END
p
info
타임스탬프 행의 패턴을 확인하는 다음과 같이 작성할 수도 있습니다 .
awk -vinfo='INF99+' \
'/^20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]/ {
if (p) { printf "%s", d }; d = ""; p=1; }
$0 ~ info {p=0}
{d = d $0 ORS}
END {if (p) printf "%s", d}' < log
일반적으로 awk
Perl이나 Perl에서 이와 같은 내용을 작성하는 것은 아마도 좋은 생각일 것입니다. 결과는 적어도 수십 개의 fork grep
, awk
등 의 복사본이 있는 쉘 스크립트보다 훨씬 빠릅니다.cut