파일 끝에서 두 번째로 나타나는 문자열 찾기

파일 끝에서 두 번째로 나타나는 문자열 찾기

다음과 같은 로그 파일이 있습니다.

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합니다 . 그런 다음 나머지 명령을 건너뛰고 다음 줄로 이동합니다.pens

  • 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 gets 버퍼.

정규식을 이해하려면 정규식이 가장 왼쪽에 있고 가장 길다는 점을 기억하세요. 선도.* 찾기마지막 게임다음 내용. Ha는 무조건 \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]. 물론 괄호 없이 단일 문자 클래스를 작성하는 것도 가능합니다.

관련 정보