다음과 같은 로그 파일이 있습니다.
Another thousand lines above this
I 10/03/15 12:04AM 42 [Important] 4th to last
I 10/03/15 04:31AM 42 (534642712) [1974,2106,258605080,0,0,32817,30711]
I 10/03/15 04:33AM 42 (2966927) [91,0,2966927,0,0,291,291]
I 10/03/15 04:52AM 42 (3026559) [93,0,3026559,0,0,314,314]
I 10/03/15 04:55AM 42 (3065494) [94,0,3065494,0,0,301,301]
I 10/03/15 05:04AM 42 [Important] 3rd to last
I 10/04/15 12:04AM 42 [Important] 2nd to last occurence
I 10/04/15 04:31AM 42 (7,30711]55
I 10/04/15 04:33AM 42 dfsadfs,0,0,291,291]
I 10/04/15 04:52AM 42 (30,0,314,314]
I 10/04/15 04:55AM 42 (30,301]
I 10/04/15 05:04AM 42 [Important] - last occurence
파일 전체에서 일정하게 유지되는 유일한 패턴은 [Important]
각 발생 사이의 줄 수를 포함하여 다른 모든 것이 변경된다는 것입니다.[Important]
파일의 끝을 가져오려고 합니다. 마지막 항목을 무시하고 마지막 항목에서 두 번째 항목을 찾은 다음 나머지 파일을 다른 파일로 추출하려고 합니다.
이것이 내가 시도한 것이지만 tac을 사용하면 마지막에서 두 번째 발생을 선택할 수 없습니다. 나는 무엇을 노력하고 있습니까?
<logfile tac | sed '/Important/q' | tac > output_file
출력은 다음과 같아야 합니다..
I 10/04/15 12:04AM 42 [Important] 2nd to last occurence
I 10/04/15 04:31AM 42 (7,30711]55
I 10/04/15 04:33AM 42 dfsadfs,0,0,291,291]
I 10/04/15 04:52AM 42 (30,0,314,314]
I 10/04/15 04:55AM 42 (30,301]
I 10/04/15 05:04AM 42 [Important] - last occurence
답변1
"중요"가 있는 모든 줄을 찾고, 마지막 두 줄을 선택하고, 줄 번호를 얻고, 범위를 인쇄합니다.
sed -n `grep -n Important log | tail -n 2 | cut -d : -f 1 | tr '\n' ',' | sed -e 's#,$#p#'` log
출력은 예상대로입니다.
I 10/04/15 12:04AM 42 [Important] 2nd to last occurence
I 10/04/15 04:31AM 42 (7,30711]55
I 10/04/15 04:33AM 42 dfsadfs,0,0,291,291]
I 10/04/15 04:52AM 42 (30,0,314,314]
I 10/04/15 04:55AM 42 (30,301]
I 10/04/15 05:04AM 42 [Important] - last occurence
스크립트로:
#!/bin/bash
lines=`grep -n Important log | tail -n 2 | cut -d : -f 1`
range=`echo "${lines}" | tr '\n' ',' | sed -e 's#,$#p#'`
sed -n "${range}" log
답변2
$ awk '/Important/{pen=s; s=$0;next} s{s=s"\n"$0} END{print pen "\n" s}' logfile
I 10/04/15 12:04AM 42 [Important] 2nd to last occurence
I 10/04/15 04:31AM 42 (7,30711]55
I 10/04/15 04:33AM 42 dfsadfs,0,0,291,291]
I 10/04/15 04:52AM 42 (30,0,314,314]
I 10/04/15 04:55AM 42 (30,301]
I 10/04/15 05:04AM 42 [Important] - last occurence
어떻게 작동하나요?
awk는 입력 파일의 모든 행을 암시적으로 반복합니다. 각 발생 후에는 Important
이 행을 변수에 저장합니다 s
. 새 행에 도달하면 Important
중요한 행의 이전 집합이 변수로 전송되고 pen
그 안에 새 행이 저장되기 시작합니다 s
.
pen
두 번째(두 번째) 부분이 있습니다 Important
. s
마지막(마지막) Important
부분이 있습니다. 마지막으로 pen
합계를 인쇄합니다 s
.
더 자세하게:
/Important/{pen=s; s=$0;next}
행에 가 포함되어 있으면
Important
변수의 내용을 로 이동하여 현재 행을 저장s
합니다 . 그런 다음 나머지 명령을 건너뛰고 다음 줄로 이동합니다.pen
s
s{s=s"\n"$0}
여기에 오면 현재 줄에는
Important
.s
값으로 설정된 경우 현재 행을 해당 값에 추가합니다.END{print pen "\n" s}
파일 끝에 도달한 후
pen
합계를 인쇄합니다s
.
답변3
ed
옵션인 경우 :
ed -s file <<EOF
1
?Important
?
;w output_file
Q
EOF
답변4
sed가 전체 파일을 버퍼링할 수 있다면(GNU 등을 사용하는 경우 가능합니다)
(마지막 편집: 여기에서 여러 개의 Brainos를 수정했습니다)
sed -En 'H;$!d
g;s/.*[\n](.*Important.*\n.*Important[^\n]*).*/\1/p
'
파일 끝까지 각 줄을 버퍼링 H;$!d
("보류") 합니다. \n
다음은 $!d
마지막 줄이 버퍼링된 후에만 실행됩니다. g
g
ets 버퍼.
정규식을 이해하려면 정규식이 가장 왼쪽에 있고 가장 길다는 점을 기억하세요. 선도.* 찾기마지막 게임다음 내용. H
a는 무조건 \n
앞에 추가 되므로 .*\n
두 개의 "유효" 앞에 있는 모든 줄과 그 사이에 최소한 하나의 개행 문자가 있고 그 뒤에는 다음 줄 앞에 있는 모든 항목이 일치합니다.
중요한 두 줄이 없으면 아무 것도 인쇄되지 않습니다.
필요하지 않은 선을 찾으면 점차적으로 버리는 것이 적어도 미학적으로 더 좋습니다.
sed -En 'H
/Important/ {x; s/.*[\n](.*Important.*\n.*Important[^\n]*)/\1/; H}
$ {g; s/.*[\n](.*Important.*\n.*Important[^\n]*).*/\1/p }
'
/Important/
변경 패턴과 보유 버퍼를 일치시키고 x
관심 있는 마지막 블록만 유지하며 결과를 다시 보유 버퍼에 넣습니다.
강조 표시하고 줄 바꿈이 아닌 후행 클래스와 시각적으로 일치시키기 위해 괄호 안에 넣을 것입니다 [\n]
. 물론 괄호 없이 단일 문자 클래스를 작성하는 것도 가능합니다.