![awk에서 이 텍스트를 일치시키고 일치하는 줄 번호를 인쇄하려면 어떻게 해야 합니까?](https://linux55.com/image/19384/awk%EC%97%90%EC%84%9C%20%EC%9D%B4%20%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%A5%BC%20%EC%9D%BC%EC%B9%98%EC%8B%9C%ED%82%A4%EA%B3%A0%20%EC%9D%BC%EC%B9%98%ED%95%98%EB%8A%94%20%EC%A4%84%20%EB%B2%88%ED%98%B8%EB%A5%BC%20%EC%9D%B8%EC%87%84%ED%95%98%EB%A0%A4%EB%A9%B4%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%ED%95%B4%EC%95%BC%20%ED%95%A9%EB%8B%88%EA%B9%8C%3F.png)
나는 다음과 같은 많은 시퀀스를 포함하는 수천 개(약 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}
'