? :,?!의 차이점은 무엇입니까? 및? = 정규식에서?


107

이 표현들의 의미를 찾았지만 정확한 차이점을 이해하지 못했습니다. 이것이 그들이 말하는 것입니다.

  • ?: 표현식과 일치하지만 캡처하지는 않습니다.
  • ?= 접미사와 일치하지만 캡처에서 제외합니다.
  • ?! 접미사가 없으면 일치합니다.

나는 이것을 간단한 RegEx에서 사용해 보았고 모두에게 비슷한 결과를 얻었습니다. 예 : 다음 3 개의 표현식은 매우 유사한 결과를 제공합니다.

  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?!\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?=\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9]+)*

테스트 케이스를 보여주세요. 동일한 결과를 제공해서는 안됩니다.
Bergi

@ sepp2k, 거의 동일한 결과를 얻지 못했으며 그중 하나가 질문에 언급되었습니다.
RK Poddar

@Bergi, 난 등 영어 단어, 전화 번호, URL을, 전자 메일 주소, 숫자를 포함하는 임의의 데이터로 테스트 ..
RK 포 다르

4
@RKAgarwal 아, 당신이 거기서 뭘했는지 봅니다. *그룹 뒤에 추가 했으므로 무시됩니다.
sepp2k

noobie note : 괄호 시작 부분에만 사용하고 괄호는 캡처 그룹을 형성합니다 (다른 괄호 세트는 텍스트의 다른 섹션을 추출합니다).
Ryan Taylor

답변:


152

의 차이 ?=와는 ?!전자가 일치하도록 주어진 식을 필요로하며, 후자는 그것을하는 데 필요한 것입니다 하지 일치합니다. 예를 들어 a(?=b)"ab"의 "a"는 일치하지만 "ac"의 "a"는 일치하지 않습니다. 반면 a(?!b)"ac"의 "a"는 일치하지만 "ab"의 "a"는 일치하지 않습니다.

의 차이 ?:와는 ?=?=동안 제외 전체 경기에서 표현 ?:단지 캡처 그룹을 만들지 않습니다. 예를 들어 a(?:b)"abc"의 "ab"와 일치하는 반면 "abc" a(?=b)의 "a"만 일치합니다. a(b)"ABC"에서 "AB"를 일치합니다 은 "B"를 포함하는 캡처를 만들 수 있습니다.


80
?:  is for non capturing group
?=  is for positive look ahead
?!  is for negative look ahead
?<= is for positive look behind
?<! is for negative look behind

여기에서 확인하십시오 : http://www.regular-expressions.info/lookaround.html 정규식의 lookahead에 대한 아주 좋은 자습서 및 예제를 보려면.


15
그러나 JavaScript는 lookbehind를 알지 못합니다.
Bergi

1
이것은 일반 정규식에 대해 더 완벽합니다.
Yan Yang

/ (? <= ^ a) b / 자바 스크립트에서 나를 위해 일했습니다! 인터넷에서 자바 스크립트를 살펴 보는 튜토리얼이없는 것 같습니다.
Y. Yoshii

브라우저의 최신 버전은 JS에서 지원하는 표정 뒤에를 시작했습니다
anubhava

– anubhava 순수한 정규 표현식을 사용하는 / (? <= ^ a) b /의 대안을 모릅니다. 아마도 할 수 있지만 콜백 함수에 의존해야합니다.
Y. Yoshii

21

더 잘 이해하기 위해 세 가지 표현식과 캡처 링 그룹을 적용하고 각 동작을 분석해 보겠습니다.

  • () 캡처 링 그룹 -괄호 안의 정규식이 일치해야하며 일치하면 캡처 링 그룹이 생성됩니다.
  • (?:) 비 캡처 그룹 -괄호 안의 정규식이 일치해야하지만 캡처 그룹을 생성하지 않습니다.
  • (?=) 긍정적 인 전망 -정규식이 일치해야한다고 주장합니다.
  • (?!) 부정적인 전망 -정규식과 일치하는 것이 불가능하다고 주장합니다.

의 적용합시다 q(u)i종료합니다 . qq일치 하고 캡처 그룹 은 u 와 일치 합니다. 캡처 그룹 내에서 일치하는 항목을 가져오고 캡처 그룹이 생성됩니다. 그래서 엔진은 . 그리고 i 와 일치 합니다. 이 마지막 경기 시도는 성공했습니다. qui 가 일치되고 u 와 함께 캡처 링 그룹 이 생성됩니다.uii

의 적용합시다 q(?:u)i종료합니다 . 다시, qq일치 하고 비 캡처 그룹 은 u 와 일치 합니다. 비 캡처 그룹의 일치 항목을 가져 오지만 캡처 그룹은 생성되지 않습니다. 그래서 엔진은 . 그리고 i 와 일치 합니다. 이 마지막 경기 시도는 성공했습니다. qui 가 일치합니다uii

의 적용합시다 q(?=u)i종료합니다 . 예견은 긍정적이고 다른 토큰이 뒤 따릅니다. 다시 말하지만, q일치 Qu일치 U를 . 다시 말하지만, 미리보기의 일치 항목을 삭제해야하므로 엔진 i은 문자열에서 u로 되돌아갑니다 . 예견이 성공 했으므로 엔진은 i. 그러나 ui 와 일치 할 수 없습니다 . 그래서이 매치 시도는 실패합니다.

의 적용합시다 q(?=u)u종료합니다 . 예견은 긍정적이고 다른 토큰이 뒤 따릅니다. 다시 말하지만, q일치 Qu일치 U를 . 미리보기의 일치 항목을 삭제해야하므로 엔진 u은 문자열에서 u로 되돌아갑니다 . 예견이 성공 했으므로 엔진은 u. 그리고 uu 와 일치 합니다. 그래서이 매치 시도는 성공했습니다. qu 가 일치합니다.

의 적용합시다 q(?!i)u종료합니다 . 이 경우에도 예견은 긍정적이고 ( i일치하지 않기 때문에 ) 다른 토큰이 뒤 따릅니다. 다시 말하지만, q일치하는 질문을 하고 i일치하지 않는 유를 . 미리보기의 일치 항목을 삭제해야하므로 엔진 u은 문자열에서 u로 되돌아갑니다 . 예견이 성공 했으므로 엔진은 u. 그리고 uu 와 일치 합니다. 그래서이 매치 시도는 성공했습니다. qu 가 일치합니다.

결론적으로, 미리보기 그룹과 비 캡처 그룹의 실제 차이점은 존재를 테스트하거나 일치를 테스트하고 저장하려는 경우에 관한 것입니다. 캡처 그룹은 비용이 많이 들기 때문에 신중하게 사용하십시오.


> 엔진은 문자열의 i에서 u로 되돌아갑니다. 예견이 성공적 이었으므로 엔진은 i로 계속됩니다. 그러나 나는 u와 일치 할 수 없습니다 . 이것은 완전히 혼란 스럽습니다. 이것이 예견 이라면 왜 뒤로 물러나 ?
Green

1
@Green lookahead 및 기타 lookaround 구성에 대해 이해해야 할 중요한 점은 하위 표현이 일치하는지 확인하기 위해 동작을 거치지 만 실제로 텍스트를 "소비"하지는 않는다는 것입니다. 즉 약간 혼동 될 수 있습니다
freedev

7

foobar다음 항목과 일치시켜보십시오 .

/foo(?=b)(.*)/
/foo(?!b)(.*)/

첫 번째 정규식은 일치하고 첫 번째 하위 (?=b)일치 로 "bar"를 반환 합니다. 'b'와 일치하지만 소비하지 않고 다음 괄호로 남겨 둡니다.

두 번째 정규식은 "foo"뒤에 'b'와 다른 것이 올 것으로 예상하기 때문에 일치하지 않습니다.

(?:...)simple과 정확히 동일한 효과가 (...)있지만 해당 부분을 부분 일치로 반환하지 않습니다.


0

어설 션을 이해하는 가장 간단한 방법은이를 정규식에 삽입 된 명령으로 처리하는 것입니다. 엔진이 어설 션을 실행하면 어설 션에 설명 된 조건을 즉시 확인합니다. 결과가 참이면 정규식을 계속 실행하십시오.


0

이것이 진짜 차이점입니다.

>>> re.match('a(?=b)bc', 'abc')
<Match...>
>>> re.match('a(?:b)c', 'abc')
<Match...>

# note:
>>> re.match('a(?=b)c', 'abc')
None

"? :"또는 "? ="다음의 내용을 신경 쓰지 않으면 "? :"및 "? ="는 동일합니다. 둘 다 사용해도 괜찮습니다.

그러나 추가 프로세스를 위해 이러한 콘텐츠가 필요한 경우 (단지 전체 일치가 아닙니다.이 경우 단순히 "a (b)"를 사용할 수 있습니다.) 대신 "? ="를 사용해야합니다. 원인 "? :"은 그냥 지나갈 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.