정규식의 일부와 일치하지만 캡처하지 않는 방법은 무엇입니까?


209

문자열 목록이 있습니다. 그들 중 일부는 형태 123-...456입니다. 변수 부분 "..."은 다음과 같습니다.

  • 문자열 "apple"다음에 하이픈 (예 : 하이픈) 123-apple-456
  • 문자열 "banana"뒤에 하이픈 (예 : 하이픈) 123-banana-456
  • 빈 문자열 (예 : 123-456하나의 하이픈 만 있음)

"apple"또는 "banana"이외의 단어는 유효하지 않습니다.

이 세 가지 경우 각각 "apple", "banana"및 ""와 일치 시키려고합니다. 하이픈을 캡처 하고 싶지 는 않지만 항상 일치 시키고 싶습니다 . 문자열이 123-...456위에서 설명한 형식이 아닌 경우 전혀 일치하지 않습니다.

이를 위해 정규식을 어떻게 작성합니까? 미리보기, 뒤로보기, 둘러보기 및 비 캡처 그룹을 허용하는 맛이 있다고 가정합니다.


여기서 중요한 점은 "사과"또는 "바나나" 가있는 경우 끝에 하이픈이 있어야 하지만 일치하지는 않는 것입니다. 빈 문자열을 일치시킬 때 뒤에 하이픈이 없어야합니다 . 이 주장을 캡슐화하는 정규식이 올바른 것이라고 생각합니다.


하이픈을 제외한 모든 것을 일치시키고 싶습니까?
BrunoLM

답변:


285

무언가를 캡처하지 않는 유일한 방법은 둘러보기 어설 션을 사용하는 것입니다 .

(?<=123-)((apple|banana)(?=-456)|(?=456))

캡처하지 않은 그룹(?:…) 의 경우에도 정규 표현식 전체가 일치하는 내용을 캡처합니다. 그러나이 정규 표현식은 일치 apple또는 banana이 앞에있어 경우 123-와 다음 -456, 또는이 앞에있어 경우는 빈 문자열과 일치 123-하고 다음에 456.

|Lookaround  |    Name      |        What it Does                       |
-----------------------------------------------------------------------
|(?=foo)     |   Lookahead  | Asserts that what immediately FOLLOWS the |
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?<=foo)    |   Lookbehind | Asserts that what immediately PRECEDES the|
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?!foo)     |   Negative   | Asserts that what immediately FOLLOWS the |
|            |   Lookahead  |  current position in the string is NOT foo|
-------------------------------------------------------------------------
|(?<!foo)    |   Negative   | Asserts that what immediately PRECEDES the|
|            |   Lookbehind |  current position in the string is NOT foo|
-------------------------------------------------------------------------

1
+1 —이 경우 그룹 0이 아닌 그룹 1을 사용하여이 문제를 해결할 수 있지만 이는 탁월한 (미묘한) 구별입니다.
Ben Blank

@Ben Blank : "일치"와 "캡처"의 해석 방법에 따라 다릅니다.
Gumbo

8
자바 스크립트에서 지원되지 야호 ! JS 친화적 인 방법을 사용하는 것이 좋지만 전혀 나쁘지 않습니다. +0.5 (반올림; D)
GiantCowFilms

둘러보기 어설 션을 사랑하십시오! 이것들은 Ruby에서도 잘 작동합니다.
Rots

완벽한 해결책, 나는 이것을 좋아한다
Trần Quang Hiệp

15

업데이트 : Germán Rodríguez Herrera에게 감사합니다!

자바 스크립트에서 시도하십시오 : /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

결과는 그룹 1에 있음을 기억하십시오

Debuggex 데모


8

시험:

123-(?:(apple|banana|)-|)456

, 또는 빈 문자열 과 일치 apple하며 그 banana뒤에 0 또는 1 개의 하이픈이 있습니다. 나는 캡처 그룹이 필요하지 않은 것에 대해 틀렸다. 바보 나.


예를 들어 "123-coconut-456"과 일치하므로 올바르지 않습니다.
David Stone

더 일반적인 것을 원한다고 생각했습니다 ... 고정되었습니다.
Thomas

5

답변 중 하나를 수정했습니다 (@ op1ekun에 의해).

123-(apple(?=-)|banana(?=-)|(?!-))-?456

그 이유는 @ op1ekun의 답변도 "123-apple456"사과 뒤에 하이픈없이 일치하기 때문 입니다.


3

이 시도:

/\d{3}-(?:(apple|banana)-)?\d{3}/

1
예를 들어 "123-coconut-456"과 일치하므로 올바르지 않습니다.
David Stone

@david : "바나나"예제와 어떻게 다릅니 까?
SilentGhost

@SilentGhost : 나는 단지 캡처 할 apple또는 banana""나. 내가 언급했듯이 다른 모든 값은 유효하지 않습니다.
David Stone

SRY,이 경우에 : ? / \ D {3} - (? :( 사과 | 바나나) -) \ D {3} /
slosd

1
이 예가 보여주는 것은 lookahead와 lookbehind를 사용하지 않고 캡처하지 않는 그룹을 가질 수 있다는 것입니다.
빈스 파누치

0

\K일치에 숫자 블록이 포함되지 않도록 일치 위치를 재설정 하는 데 사용되는 @Gumbo의 변형 표현 입니다. PCRE 정규식 맛에 사용할 수 있습니다.

123-\K(?:(?:apple|banana)(?=-456)|456\K)

성냥:

Match 1  apple
Match 2  banana
Match 3

-3

지금까지 가장 간단한 방법은 (python에서 작동)입니다 '123-(apple|banana)-?456'.


1
일치 123-apple456하지 않으므로 올바르지 않습니다.
Loren
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.