프로세스의 출력을 보고하는 로그 파일이 있고 두 패턴의 마지막 발생에서 모든 행을 추출하고 싶습니다.
이러한 패턴은 다음과 같은 라인을 따릅니다.
Summary process started at <datestring>
그리고
Summary process finished at <datestring> with return code <num>
다른 많은 정보와 함께 파일 전체에 이러한 패턴의 여러 인스턴스가 있습니다. 마지막 항목만 인쇄하고 싶습니다.
다음을 사용할 수 있다는 것을 알고 있습니다.
sed -n '/StartPattern/,/EndPattern/p' FileName
패턴 사이의 선을 파악했지만 이를 얻는 방법을 모릅니다.마지막예.
sed
아니면 awk
해결책이 나올 것입니다.
편집하다:StartPatterns
multiple EndPattern
. EndPattern
StartPattern
StartPattern
누락된 s가 여러 개인 경우 마지막 행부터 까지의 행만EndPattern
원합니다 .StartPattern
EndPattern
- 안 오는 건
StartPattern
다 왔으면 좋겠고, 그 다음에는 조기 도착 주의가 있어요.EOF
EndPattern
EOF
EOF
답변1
언제든지 다음과 같이 할 수 있습니다.
tac < fileName | sed '/EndPattern/,$!d;/StartPattern/q' | tac
시스템에 GNU가 없다면 tac
이를 사용할 수도 있습니다 tail -r
.
다음과 같이 할 수도 있습니다.
awk '
inside {
text = text $0 RS
if (/EndPattern/) inside=0
next
}
/StartPattern/ {
inside = 1
text = $0 RS
}
END {printf "%s", text}' < filename
그러나 이는 전체 파일을 읽는 것을 의미합니다.
StartPattern
a와 다음 사이에 다른 것이 있거나, 마지막 것이 끝나지 않거나, a와 일치하는 줄이 있는 경우에는 다른 결과가 나타날 수 있습니다 .StartPattern
EndPattern
StartPattern
EndPattern
StartPattern
EndPattern
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {printf "%s", text}' < filename
tac+sed+tac
(닫히지 않은 후행 사례를 제외하고 ) 해당 방법과 더 유사하게 작동하게 됩니다 StartPattern
.
마지막 항목이 편집자가 원하는 것과 가장 가까운 것 같습니다. 경고를 추가하려면 다음을 수행하십시오.
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {
printf "%s", text
if (inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
}' < filename
전체 파일을 읽지 않으려면 다음을 수행하십시오.
tac < filename | awk '
/StartPattern/ {
printf "%s", $0 RS text
if (!inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
exit
}
/EndPattern/ {inside = 1; text = ""}
{text = $0 RS text}'
이식성 참고: /dev/stderr
)에 대한 특수 파일이 있는 시스템이나 awk
이를 에뮬레이트하는 구현(예: gawk
, mawk
busybox) 이 필요합니다 awk
(위에서 언급한 Linux 문제를 해결함).
print ... > "/dev/stderr"
다른 시스템에서는 로 바꿀 수 있습니다 print ... | "cat>&2"
.
답변2
sed
GNU를 이렇게 사용할 수 있습니다
sed '/START/{:1;$!{/END/!{N;b1};h}};${x;p};d' file
전체 여러 줄 패턴이 나타날 때마다 예약된 공간을 덮어쓰세요. 파일 끝에 인쇄하세요.
이는 일관된 동작을 제공합니다.
- 같은 줄에 있는 START와 END는 모두 줄과 일치합니다.
- 초기 START 이후의 여러 START는 END까지 모두 일치합니다.
- END가 없으면 일치 항목이 인쇄되지 않으며 전체 START에서 END까지의 마지막 항목이 인쇄됩니다.
답변3
의 경우 GNU sed
다른 솔루션은 다음과 같습니다(변수 P1
/를 P2
시작/종료 패턴으로 사용).
sed -n "/${P1}/,/${P2}/H; /${P1}/h; \${g;p}"
@Stéphane Chazelas의 솔루션과의 주요 차이점은 다음과 같습니다.
- 마지막 END/EOF 이전에 여러 개의 START가 있는 경우 마지막 START부터 마지막 END/EOF까지 표시됩니다.
- START와 같은 줄에 있는 모든 END는 무시됩니다.
- 마지막 입력 라인에서 마지막 END 지원
- 마지막 START 이후에 END가 없으면 마지막 START부터 EOF까지 인쇄합니다.
답변4
awk의 솔루션은 다음과 같습니다.
awk '/EndPattern/ {recording=0} recording>0 {buffer=buffer $0 "\n"} /StartPattern/ {recording+=1; buffer=""} END {printf "%s", buffer; if(recording>0) {print "WARNING: missing EndPattern" > "/dev/stderr"}}'
따라서 다음 입력의 경우:
1
StartPattern
2
3
EndPattern
4
5
StartPattern
6
7
EndPattern
8
다음과 같은 결과가 출력됩니다.
6
7
정확한 라인 일치를 원할 경우 StartPattern을 ^StartPattern$로 바꾸고 EndPattern도 마찬가지입니다. 중첩된 패턴을 무시하려면 Recording+=1을 Recording=1로 바꿀 수도 있습니다.