내부 상태를 다시 시작하는 장기 실행 프로그램이 있습니다. 로그 파일 항목( vim
빠른 수정사항에 로드됨)의 최신 상태만 보고 싶습니다 . 이후의 모든 줄을 표시하는 방법마지막문자열의 발생 STARTING SESSION
?
내 현재 솔루션(로그 파일의 길이가 GB에 달하는 경우가 있으므로 마지막 5000줄 이상은 확인하지 않습니다):
tail -n5000 logfile.log | grep -B5000 -v -e 'STARTING SESSION'> shortened.log
이는 세션에서 많은 로깅이 생성될 때 잘 작동하지만 로그가 더 짧고 여러 번 다시 시작되면 여러 세션에 걸쳐 발생합니다.
--reverse
본질적으로 나는 파일의 처음이 아닌 끝에서 grep 검색을 수행하는 플래그 와 같은 것을 원합니다 .
grep --reverse --after-context=5000 --max-count=1 'STARTING SESSION' logfile.log
노트:
질문은 다음과 같습니다.n번째 일치 항목이 발생한 후 줄을 인쇄합니다., 하지만 마지막으로 한 번 더 나타나고 싶었어요.
문제는 거의 똑같습니다POSIX.2의 마지막 토큰에서 EOF로 텍스트 가져오기단지 POSIX 요구 사항이 없고 파일이 크기 때문일 뿐입니다. 나는 GNU 유틸리티(내가 사용하고 있는 mingw64
)를 사용하는 효율적인 솔루션을 선호합니다.
답변1
파일을 반전시켜 처음 나타날 때까지 표시한 다음 출력을 다시 반전시킵니다.
tac logfile.log | sed '/STARTING SESSION/q' | tac
tac
처리할 일반(검색 가능한) 파일이 제공되면 유효합니다.sed
, 시작 줄이 보이자마자 종료 하므로 전체 파이프라인은 필요한 경우에만 로그 파일의 끝을 처리합니다( tac
's, sed
's 및 커널 버퍼 크기로 반올림됨). 이는 대용량 파일에 맞게 확장되어야 합니다.
tac
GNU 유틸리티입니다. GNU가 아닌 시스템에서는 일반적 tail -r
으로 .
로그 파일에 "STARTING SESSION" 줄이 전혀 없으면 사용자와 동일한 동작이 생성되지 않습니다 grep
. 전체 로그 파일이 출력됩니다. 이를 방지하기 위해 변형이 있습니다.코살로난다의 방법다음을 사용할 수 있습니다:
tac logfile.log | sed -n '/STARTING SESSION/{H;x;p;q;};H' | tail -n +2 | tac
표현식은 sed
"STARTING SESSION"을 찾고, 일치할 때 현재 행을 보유 공간에 추가하고, 보유 공간을 패턴 공간으로 바꾸고, 인쇄하고 종료합니다. 추가 행이 보유 공간에 추가됩니다. tail -n +2
첫 번째 빈 줄을 건너뛰는 데 사용됩니다(예약된 공간에 패턴 공간을 추가하면 앞에 줄 바꿈이 추가됩니다).
답변2
사용sed
아니요tac
:
sed \
-e '/STARTING SESSION/h' \
-e '//,$ { //!H; }' \
-e '$!d' \
-e x logfile.log
또는 ;
한 줄의 표현식 사이에 사용됩니다.
sed '/STARTING SESSION/h; //,$ { //!H; }; $!d; x' logfile.log
주석이 달린 변형:
# If this line matches our trigger, save buffer in hold-space (overwrites).
/STARTING SESSION/ h
# In the range from the trigger to the end, append buffer to hold-space,
# but only if the current line isn't the trigger.
# (// re-uses the most recent expression)
//,$ { //!H; }
# If we're not at the end, restart with the next line without outputting anything.
$! d
# At the end, swap the hold-space into the buffer.
x
# (buffer is implicitly printed)
요약: 이 sed
스크립트는 트리거와 문서 끝 사이의 모든 줄을 저장합니다 sed
. 트리거가 발견될 때마다 보관 공간이 지워집니다. 마지막으로 출력은 간격을 유지합니다.
트리거가 발견되지 않으면 출력이 생성되지 않습니다.
또한 전체 파일을 읽어야 합니다.
유사한 방법 awk
:
awk '
/STARTING SESSION/ { delete hold; i = 1 }
i { hold[i++] = $0 }
END { for (j = 1; j < i; j++) print hold[j] }' logfile.log
hold
여기서 트리거가 발견되면( i
처음 1로 설정했을 때) 배열에서 데이터 수집을 시작합니다. 수집된 데이터를 삭제하고 i
트리거할 때마다 1로 재설정합니다.
마지막으로 수집된 모든 행이 출력됩니다.
이 delete hold
설명은 꼭 필요한 것은 아닙니다.