developer tip

grep에서 '뒤에없는'에 대한 정규식 미리보기

copycodes 2020. 9. 3. 20:02
반응형

grep에서 '뒤에없는'에 대한 정규식 미리보기


나는 Ui\.뒤 따르지 않는 모든 경우 Line또는 심지어 편지에 대해 grep을 시도하고 있습니다.L

다른 문자열이 뒤 따르지 않는 특정 문자열의 모든 인스턴스를 찾기 위해 정규식을 작성하는 적절한 방법은 무엇입니까?

미리보기 사용

grep "Ui\.(?!L)" *
bash: !L: event not found


grep "Ui\.(?!(Line))" *
nothing

당신이 추구하는 부정적 예측은 표준보다 더 강력한 도구가 필요합니다 grep. PCRE 사용 grep이 필요합니다.

GNU grep가있는 경우 현재 버전이 옵션을 지원 -P하거나 --perl-regexp원하는 정규식을 사용할 수 있습니다.

당신이 (충분히 최신 버전) GNU이없는 경우 grep, 다음 고려지고 ack.


문제의 일부에 대한 답은 여기에 있으며 ack는 동일한 방식으로 작동합니다. 오류를주는 Ack 및 부정적 예측

grep에 큰 따옴표를 사용하여 bash가 " !히스토리 확장 명령으로 해석"할 수 있도록 합니다.

패턴을 단일 따옴표로 감싸 야합니다. grep 'Ui\.(?!L)' *

그러나 표준에서 부정적인 예견 문제를 해결하려면 @JonathanLeffler의 답변참조하십시오 grep!


grep을 사용하여 표준 부정 예측을 수행 할 수는 없지만 일반적으로 "inverse"스위치 '-v'를 사용하여 동등한 동작을 얻을 수 있습니다. 이를 사용하여 일치하려는 항목의 보완을위한 정규식을 구성한 다음 2 개의 greps를 통해 파이프 할 수 있습니다.

문제의 정규식의 경우 다음과 같이 할 수 있습니다.

grep 'Ui\.' * | grep -v 'Ui\.L'

네거티브 룩어 헤드를 지원하지 않는 정규식 구현을 사용해야하고 추가 문자 * 일치에 신경 쓰지 않는다면 부정 문자 클래스[^L] , alternation|문자열 anchor$끝을 사용할 수 있습니다 .

귀하의 경우 grep 'Ui\.\([^L]\|$\)' *에는 일을합니다.

  • Ui\. 관심있는 문자열과 일치합니다.

  • \([^L]\|$\)다른 단일 문자 L와 일치 [^L]하거나 줄의 끝과 일치합니다 : 또는 $.

둘 이상의 캐릭터를 제외하려면 더 많은 교대와 부정을 던져야합니다. a뒤 따르지 않는 것을 찾으려면 bc:

grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *

다음 중 하나는 ( a뒤에 not b또는 그 뒤에 줄 끝 : athen [^b]또는 $) 또는 ( a뒤에 bnot c뒤에 있거나 줄의 끝 : athen b, then [^c]또는 $.

이런 종류의 표현은 매우 다루기 어렵고 짧은 문자열로도 오류가 발생하기 쉽습니다. 표현식을 생성하기 위해 무언가를 작성할 수 있지만 부정적인 예측을 지원하는 정규식 구현을 사용하는 것이 더 쉬울 것입니다.

* 구현이 비 캡처 그룹지원하는 경우 추가 문자 캡처를 피할 수 있습니다.


grep이 -P 또는 --perl-regexp를 지원하지 않고 PCRE 사용 grep (예 : "pcregrep")을 설치할 수있는 경우 Perl 호환 일반을 허용하기 위해 GNU grep과 같은 명령 줄 옵션이 필요하지 않습니다. 식, 당신은 그냥 실행

pcregrep "Ui\.(?!Line)"

"Ui. (?! (Line))"예제에서와 같이 "Line"에 대해 다른 중첩 그룹이 필요하지 않습니다. 위에서 설명한 것처럼 외부 그룹이면 충분합니다.

부정적인 어설 션을 보는 또 다른 예를 들겠습니다. "ipset"에 의해 반환 된 라인 목록이 있고 라인 중간에 패킷 수를 표시하는 각 라인이 있고 패킷이없는 라인이 필요하지 않은 경우 운영:

ipset list | pcregrep "packets(?! 0 )"

perl 호환 정규식을 좋아하고 perl이 있지만 pcregrep이 없거나 grep이 --perl-regexp를 지원하지 않는 경우 grep과 같은 방식으로 작동하는 한 줄 perl 스크립트를 사용할 수 있습니다.

perl -e "while (<>) {if (/Ui\.(?!Lines)/){print;};}"

Perl은 grep과 같은 방식으로 stdin을 허용합니다.

ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"

참고 URL : https://stackoverflow.com/questions/9197814/regex-lookahead-for-not-followed-by-in-grep

반응형