[Regex] grep에서 non-greedy match를하는 방법?


Answers

욕심이없는 (또는 게으른) 경기를 찾고 있습니다. 정규 표현식에서 욕심없는 일치를 얻으려면 수식어를 사용해야 ? 한정 기호 뒤에. 예를 들어 .* .*? .

기본적으로 grep 은 non-greedy 수정자를 지원하지 않지만 grep -P 를 사용하여 Perl 구문을 사용할 수 있습니다.

Question

가장 짧은 시합을 grep하고 싶고 패턴은 다음과 같아야합니다.

<car ... model=BMW ...>
...
...
...
</car>

...는 모든 문자를 의미하며 입력은 여러 줄입니다.




짧은 대답은 다음 정규식을 사용하는 것입니다.

(?s)<car .*? model=BMW .*?>.*?</car>
  • (? s) - 여러 줄에 걸쳐 일치시킵니다.
  • . *? - 모든 문자, 게으른 방식으로 여러 번 일치 (최소 일치)

(조금) 더 복잡한 대답은 다음과 같습니다.

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>

이렇게하면 다음 텍스트에서 car1과 car2를 일치시킬 수 있습니다.

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
  • (..)는 캡처 그룹을 나타냅니다.
  • 이 컨텍스트에서 \ 1은 그룹 번호 1을 캡처하여 가장 최근에 일치 한 sametext와 일치합니다.



grep

grep 비 탐욕적인 일치의 경우 부정 문자 클래스를 사용할 수 있습니다. 즉, 와일드 카드를 피하십시오.

예를 들어 페이지 콘텐츠에서 jpeg 파일에 대한 모든 링크를 가져 오려면 다음을 사용하십시오.

grep -o '"[^" ]\+.jpg"'

여러 줄을 처리하려면 먼저 xargs 통해 입력을 파이프하십시오. 성능을 위해서는 ripgrep 사용 ripgrep .




실제 .*? perl 에서만 작동합니다. 나는 그 grep이 regexp 신택스를 어떻게 확장하는지 확신하지 못한다. 다행스럽게도 grep과 함께 perl 구문을 사용할 수 있으므로 grep -P 가 작동하지만 grep -Eegrep 과 동일하지만 작동하지 않습니다 (greedy).

또한보십시오 : http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html




이 스레드에서 물건을 시험해보고 나서 작동하는 grep :

echo "hi how are you " | grep -shoP ".*? "

각 줄에 공백을 추가해야합니다.

(내 말은 단어를 내뱉기 위해 한 줄씩 검색했다.)