탐욕스럽지 않은 방식으로 시작 태그와 끝 태그가 있는 패턴이 있는 파일에서 여러 줄을 가져오고 싶습니다.
예를 들어 다음과 같은 입력이 있습니다.
파일.txt
START
test1
test2
foo
END
some
more text
START
test3
bar
test4
test5
END
even more
START
baz
test6
END
이제 나는 찾고 싶다술집사이의 모든 내용을 인쇄합니다.시작그리고끝, 그래서 나는 다음을 얻습니다:
START
test3
bar
test4
test5
END
지금까지 내가 가지고 있는 것은 다음 grep 명령입니다.
grep -Pzo '(?s)START.*?bar.*?END' file.txt
문제는 이 표현식이 탐욕적이어서 다음과 같이 인쇄된다는 것입니다.
START # starts at first "START"-tag, not the next one
test1 #
test2 #
foo #
END #
some #
more text #
START
test3
bar
test4
test5
END
grep 플래그가 아직 완료되지 않았습니다.--컨텍스트 전/--컨텍스트 이후, 이전과 이후의 행 수가 다를 수 있기 때문입니다.
텍스트 처리에 사용되는 도구는 중요하지 않습니다. 일반 RedHat 시스템에서 실행되어야 합니다. 또한 도구가 선을 잡는 속도가 빠를수록 좋습니다. 약 150MB의 대용량 로그 파일이 있기 때문입니다.
누군가 내 목표를 가장 잘 달성하는 방법을 말해 줄 수 있습니까?
고쳐 쓰다:
그래 알았어. don_crissti
s 링크에서 명령을 작성하는 방법만 생각하면 됩니다 . 해결책은 다음과 같습니다.
ed -s file.txt <<< $'g/bar/?START?,/END/p\nq\n'
빠른 도움을 주셔서 정말 감사합니다!
응 결국 반복이었어...
답변1
내 생각에 당신의 문제는 탐욕스럽지 않은 매치가 당신이 원하는 것보다 더 많이 먹어치울 수 있다는 것입니다.끝모래시작에스. 이것은 작동하는 것 같습니다:
grep -Pzo '(?s)START(?:(?!END).)*?bar(?:(?!START).)*?END' file.txt
예제의 모든 경우를 다루며, 완료한 경우>> file.txt
bar
START
test7
END
여전히 유효.
답변2
레코드 구분 기호를 지정할 수 있는 경우 awk를 사용하겠습니다. 레코드 구분 기호가 "END"(한 줄에)인 경우 "bar"가 포함된 레코드를 찾습니다.
awk 'BEGIN {RS = ORS = "\nEND\n"} /bar/' file.txt
START 및 END 태그 사이에 나타나는 프로세스 텍스트입니다. 이 변경 사항은 해킹된 것처럼 느껴지지만 이 경우에는 작동합니다. END를 레코드 구분 기호로 사용하고 START 키워드 앞의 모든 텍스트를 제거합니다.
awk '
BEGIN {RS = ORS = "\nEND\n"}
{sub(/^.*\nSTART\n/, "START\n")}
/bar/
' file.txt
END 앞에 "START"가 여러 번 나타나면 원하는 결과가 나오지 않을 수 있습니다.
foo
START
hello
START
bar
world
END
baz
다음과 같이 출력됩니다.
START
bar
world
END
답변3
perl -nE 'BEGIN {$/="\nEND\n"} say /(START.*test.*)/s'
@bobbel이 지적했듯이 빈 줄 구분 기호를 피하려면 다음 say
으로 바꾸십시오.print