두 레이블 사이의 grep이 -z 옵션과 함께 작동하지 않는 이유는 무엇입니까? 어떻게 고치나요?

두 레이블 사이의 grep이 -z 옵션과 함께 작동하지 않는 이유는 무엇입니까? 어떻게 고치나요?

이 경우:

$ cat t01.txt
xxxyyyzzz

$ cat t01.txt | grep -Po '(?<=xxx).*(?=zzz)'

결과 :

yyy

이것은 예상됩니다.

그러나 이 경우는:

$ cat t02.txt
xxx
yyy
zzz

$ cat t02.txt | grep -Pzo '(?<=xxx).*(?=zzz)'

결과 :

<nothing>

이것은 예상치 못한 일입니다.

이유와 해결 방법은 무엇입니까?

답변1

기본적으로 .Perl 정규 표현식의 개행 문자는 일치하지 않습니다. 명시적으로 일치시키거나 s정규식 플래그를 사용해야 합니다.

$ < t02.txt grep -Pzo '(?<=xxx\n).*\n(?=zzz)'
yyy
$ < t02.txt grep -Pzo '(?s)(?<=xxx).*(?=zzz)'

yyy

예를 들어 참조하십시오.perlre매뉴얼 페이지:

"메타문자" 섹션에서:

.   Match any single character except newline    Not in []
    (under /s, includes newline)

그리고 "수정자"에서:

s
문자열을 한 줄로 처리합니다. 즉, "."일반적으로 일치하지 않는 모든 문자, 개행 문자까지 일치하도록 변경합니다.

답변2

이는 실제로 예상되는 동작입니다. .개행 문자를 제외한 모든 문자를 포함합니다. 찾고 있는 정규식은 다음과 같습니다.

(?<=xxx)\n*.*\n*(?=zzz)

이 사이트는 정규식을 테스트하기에 좋은 사이트이며 각 부분에 대한 설명도 포함되어 있으므로 이것이 왜 다음과 같이 작동하는지 항상 알 수 있습니다.https://regex101.com

관련 정보