awk에서 이 텍스트를 일치시키고 일치하는 줄 번호를 인쇄하려면 어떻게 해야 합니까?

awk에서 이 텍스트를 일치시키고 일치하는 줄 번호를 인쇄하려면 어떻게 해야 합니까?

나는 다음과 같은 많은 시퀀스를 포함하는 수천 개(약 148,000줄 길이)의 텍스트 파일을 가지고 있습니다.

b 29.
b 52.
c 84.
c 83.
c 94.
c 93.
c 61.
b 38.
c 81.
c 92.
c 28.
c 37.
c 27.

...파일이 너무 크기 때문에 다음과 같은 패턴을 검색할 수 있기를 바랍니다(기능적이지 않은 한 줄).

grep "b\ 34.\nc53.\nb\ 54.\na\ 45.\nd\ 44.\nd\ 63.\nd\ 64.\n" 파일 이름

awk가 좋은 선택인 것 같습니다.

이 작업을 수행하고 일치하는 줄 번호를 인쇄하려면 어떻게 해야 합니까?

답변1

이것은 여러 줄의 문자열을 검색하는 awk 스크립트입니다(일치 항목은 전체 줄로 구성되어야 함). 변수에서 검색할 텍스트를 받습니다 needle. 스크립트는 행 창 w( w의 행 수는 needle)을 작성하고 이를 와 비교하여 작동합니다 needle.

awk -v needle='b 38.\nc 81.\nc 92.\n' '
    BEGIN {
        if (substr(needle, length(needle)) == "\n")
            needle = substr(needle, 1, length(needle)-1);
        w = split(needle, needles, "\n");
        getline window
        for (i = 2; i < w; i++) {getline; window = window "\n" $0}
    }
    { window = window "\n" $0 }
    window == needle {print NR - w + 1}
    { window = substr(window, index(window, "\n") + 1) }
' <data.txt

이는 데이터 파일의 모든 줄이 패턴의 모든 줄과 비교되기 때문에 부분 문자열을 검색하는 가장 효율적인 방법은 아닙니다. 패턴에서 일부 사전 계산을 수행하여 더 적은 수의 비교를 수행하는 보다 효율적인 알고리즘이 있습니다.골드 모리스 프랫.

메모리에 맞는 파일은 한꺼번에 읽어서 메모리에서 검색을 합니다. 찾고 있는 것이 패턴 일치뿐이라면 이는 Perl에서 쉽게 수행할 수 있지만 Perl에는 효율적인 선 추적을 위한 기본 요소가 부족합니다. 다음은 여러 줄로 구성된 문자열(그대로 전달되어야 함)을 찾는 Python 스크립트입니다.

import re, sys
needle = sys.argv[1]
haystack = sys.stdin.read()
pos = 0
line = 1
for m in re.finditer(needle, haystack):
    line += haystack.count("\n", pos, m.start())
    pos = m.start()
    print line

용법:python -c '…' $'b 38.\nc 81.\nc 92.\n' <data.txt

답변2

나는 다음과 같이 쓸 것입니다 :

awk -v seven_lines="b 34.c 53.b 54.a 45.d 44.d 63.d 64." '
    seven_lines == l6 l5 l4 l3 l2 l1 $0 {print "pattern found at line " (NR-6)}
    {l6=l5; l5=l4; l4=l3; l3=l2; l2=l1; l1=$0}
'

관련 정보