[regex] 단어를 포함하지 않는 행과 일치하는 정규식

단어를 일치시킨 다음 다른 도구 (예 :)를 사용하여 일치를 되돌릴 수 있다는 것을 알고 있습니다 grep -v. 그러나 hede정규 단어 를 사용하여 특정 단어를 포함하지 않는 행을 일치시킬 수 있습니까?

입력:

hoho
hihi
haha
hede

암호:

grep "<Regex for 'doesn't contain hede'>" input

원하는 출력 :

hoho
hihi
haha



답변

정규 표현식이 역 매칭을 지원하지 않는다는 개념은 전적으로 사실이 아닙니다. 부정적인 둘러보기를 사용하여이 동작을 모방 할 수 있습니다.

^((?!hede).)*$

위의 정규 표현식 은 (하위) 문자열 ‘hede’를 포함 하지 않는 모든 문자열 또는 줄 바꿈이없는 행과 일치합니다 . 언급 한 바와 같이,이 정규식에서 “좋은”(또는해야 할) 것이 아닙니다,하지만 여전히, 그것은 이다 가능합니다.

또한 줄 바꿈 문자도 일치시켜야하는 경우 DOT-ALL 수정자를 사용하십시오 ( s다음 패턴 의 후행 ).

/^((?!hede).)*$/s

또는 인라인으로 사용하십시오.

/(?s)^((?!hede).)*$/

(여기서 /.../정규 표현식 구분 기호는 패턴의 일부가 아닙니다)

DOT-ALL 수정자를 사용할 수없는 경우 문자 클래스를 사용하여 동일한 동작을 모방 할 수 있습니다 [\s\S].

/^((?!hede)[\s\S])*$/

설명

문자열은 n문자 목록 일뿐 입니다. 각 문자 전후에 빈 문자열이 있습니다. 따라서 n문자 목록 에는 n+1빈 문자열이 있습니다. 문자열을 고려하십시오 "ABhedeCD".

    ┌──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┐
S = e1 A e2 B e3 h e4 e e5 d e6 e e7 C e8 D e9
    └──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┘

index    0      1      2      3      4      5      6      7

여기서 e의는 빈 문자열입니다. 정규 표현식 (?!hede).은 하위 문자열이 없는지 미리 "hede"보고, 그 경우 (다른 것이 보이면) .(점)은 줄 바꿈을 제외한 모든 문자와 일치합니다. 둘러보기는 문자를 소비 하지 않기 때문에 폭이 0 인 어설 션 이라고도 합니다 . 그들은 단지 무언가를 주장하고 / 확인한다.

따라서 내 예에서 모든 빈 문자열은 먼저 "hede"문자가 .(점)에 의해 소비되기 전에 선행 이 없는지 확인합니다 . 정규 표현식 (?!hede).은 한 번만 수행하므로 그룹으로 묶여 0 회 이상 반복됩니다 ((?!hede).)*. 마지막으로 입력 시작과 끝은 전체 입력이 소비되도록 고정됩니다.^((?!hede).)*$

당신이 볼 수 있듯이, 입력이 "ABhedeCD"때문에 실패합니다 e3정규식, (?!hede)실패 (가 이다 "hede" 앞두고!).


답변

해결책 “hede”로 시작 하지 않습니다 .

^(?!hede).*$

“hede”를 포함 하지 않는 솔루션보다 일반적으로 훨씬 효율적입니다 .

^((?!hede).)*$

전자는 모든 위치가 아닌 입력 문자열의 첫 번째 위치에서만 “hede”를 확인합니다.


답변

경우 그냥 그렙 위해 그것을 사용하고, 당신이 사용할 수있는 grep -v hedeHEDE를 포함하지 않는 모든 라인을 얻을 수 있습니다.

ETA 오, 질문을 다시 grep -v읽어 보면 “도구 옵션”이라는 의미 일 것입니다.


답변

대답:

^((?!hede).)*$

설명:

^문자열의 시작,
(그룹화 및 \ 1까지 캡처 (0 회 이상 (가장 많은 양과 일치))
(?!없는지 확인하십시오.

hede 당신의 줄,

)미리보기 끝,
.\ n을 제외한 모든 문자,
)*\ 1 끝 (참고 :이 캡처에서 수량 자를 사용하므로 캡처 된 패턴의 마지막 반복 만 \ 1에 저장 됨)
$옵션 \ n, 그리고 문자열의 끝


답변

주어진 대답은 학문적 요점으로 완벽하게 좋습니다.

이론적 컴퓨터 과학의 의미에서 정규 표현식은 할 수없는 다음과 같이 해. 그들에게는 다음과 같이 보일 것입니다.

^([^h].*$)|(h([^e].*$|$))|(he([^h].*$|$))|(heh([^e].*$|$))|(hehe.+$) 

이것은 전체 일치 만 수행합니다. 하위 경기를 위해 그것을하는 것은 더 어색 할 것입니다.


답변

전체 문자열이 일치 하는 경우 에만 정규식 테스트가 실패 하도록하려면 다음이 작동합니다.

^(?!hede$).*

예 :- “foo”를 제외한 모든 값을 허용하려면 (예 : “foofoo”, “barfoo”및 “foobar”는 통과하지만 “foo”는 실패 함) 다음을 사용하십시오. ^(?!foo$).*

물론, 당신이 정확한 동등성을 검사한다면 ,이 경우에 더 나은 일반적인 해결책은 문자열 동등성을 검사하는 것입니다.

myStr !== 'foo'

정규식 기능이 필요한 경우 테스트 외부 에서 부정을 넣을 수도 있습니다 (여기서는 대소 문자를 구분하지 않고 범위를 일치시킵니다).

!/^[a-f]oo$/i.test(myStr)

그러나이 답변의 맨 위에있는 정규식 솔루션은 긍정적 정규식 테스트가 필요한 경우 (아마도 API에 의해) 도움이 될 수 있습니다.


답변

FWIW는 정규 언어 (일명 합리적 언어)가 보완 아래 닫히므로 항상 다른 표현을 무효화하는 정규식 (일명 합리적인 표현)을 찾을 수 있습니다. 그러나이를 구현하는 도구는 많지 않습니다.

Vcsn 은이 연산자 ( {c}후위를 나타냄 )를 지원합니다.

먼저 표현의 유형을 정의 라벨은 편지 ( lal_char) 선택하는 제품들 a에 대한 z예를 들어 (알파벳을 정의 보완 작업을 할 때, 물론 매우 중요합니다), 각 단어에 대해 계산 된 “값이”단지 부울입니다 : true단어가 수락 false되고 거부됩니다.

파이썬에서 :

In [5]: import vcsn
        c = vcsn.context('lal_char(a-z), b')
        c
Out[5]: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}  ?

그런 다음 식을 입력하십시오.

In [6]: e = c.expression('(hede){c}'); e
Out[6]: (hede)^c

이 표현식을 자동으로 변환하십시오.

In [7]: a = e.automaton(); a

해당 오토 마톤

마지막으로,이 오토 마톤을 간단한 표현으로 다시 변환하십시오.

In [8]: print(a.expression())
        \e+h(\e+e(\e+d))+([^h]+h([^e]+e([^d]+d([^e]+e[^]))))[^]*

여기서 +일반적으로 표시되고 |, \e비어있는 단어를 의미하며, [^]일반적으로 기록된다 .(모든 문자). 약간의 재 작성으로 ()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*.

이 예제를 볼 수 있습니다 여기에 , 온라인 Vcsn 시도 .