정규식은 정확히 n 번 또는 m 번


105

다음과 같은 정규 표현식, 고려 X입니다 어떤 정규식.

X{n}|X{m}

이 정규식은 정확히 또는 시간이 X발생 하는지 테스트합니다 . nm

발생을 X정확히 n또는 m시간 테스트 할 수있는 정규식 한정자가 있습니까?


아니요. 두 번의 발생은 X일반 m, n.
존 드보락

이것이 내 문제라면 정규식 역 참조를 시도하고 (X)\1{n-1}(?:\1{m-n-1}). 나는 이것이 X적어도 한 번 일치 한다는 것을 알고 있지만 시작하려면이 간단한 것을 시도한 다음 (X). 대신 lookaheads 또는 lookbehinds를 사용하여 수정하십시오 .
nalply

답변:


91

"정확히 m 또는 n 번"을 의미하는 단일 수량자는 없습니다. 당신이하는 방식은 괜찮습니다.

대안은 다음과 같습니다.

X{m}(X{k})?

여기서 m < nand k는의 값입니다 n-m.


67

다음은 전체 수량 자 목록입니다 (참조 : http://www.regular-expressions.info/reference.html ) :

  • ?, ??-0 또는 1 회 발생 ( ??게으르고 ?탐욕 스러움)
  • *, *?-횟수 제한 없음
  • +, +?-하나 이상의 발생
  • {n}-정확히 n발생
  • {n,m}- nm발행 수, 포함
  • {n,m}?- nm발행 수, 게으른
  • {n,}, {n,}?-적어도 n발생

"정확히 N 또는 M"을 얻으려면 m, n이 특별하지 않는 한 정량화 된 정규식을 두 번 작성해야합니다.

  • X{n,m} 만약 m = n+1
  • (?:X{n}){1,2} 만약 m = 2n
  • ...

1
?:if m = 2n예제 에서 왜 필요 합니까? 그것 없이는 잘 작동하는 것 같습니다.
erb

7
@erb를 생략하면 ?:그룹이 캡처 그룹이됩니다. 정규식 엔진이 필요하지 않은 항목을 기억하는 것 외에도이 그룹 이후에 그룹을 캡처하면 해당 ID가 변경됩니다. 정규식을 대체에 사용하는 경우 대체를 조정해야합니다.
John Dvorak

19

아니요, 그러한 수량자는 없습니다. 그러나 역 추적 문제/X{m}(X{m-n})?/ 를 방지하기 위해 재구성 할 것 입니다.


3

TLDR; (?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

"xn 시간"또는 "xm 시간"을 원하는 것 같습니다. 정규식에 대한 문자 그대로 번역은 다음 (x{n}|x{m}). 과 같습니다. https://regex101.com/r/vH7yL5/1

또는 m 개 이상의 "x"시퀀스를 가질 수있는 경우 (m> n이라고 가정) 'following no "x"'및 'following no "x"를 추가하여로 번역 할 [^x](x{n}|x{m})[^x]수 있습니다. "x"뒤에 항상 문자가 있다고 가정합니다. 여기에서 볼 수 있듯이 https://regex101.com/r/bB2vH2/1

(?:[^x]|^)(x{n}|x{m})(?:[^x]|$)"뒤에 'x'또는 다음 줄 시작"및 "뒤에 'x'없음 또는 뒤에 줄 끝"으로 변환하여로 변경할 수 있습니다 . 그러나 여전히 두 시퀀스 사이에 하나의 문자 만있는 두 시퀀스는 일치하지 않습니다 (첫 번째 일치에는 다음 문자가 필요하고 두 번째 일치는 이전 문자가 필요하기 때문). https://regex101.com/r/ oC5oJ4 / 1

마지막으로, 한 문자 먼 일치를 일치시키기 위해 "no 'x'after"에 긍정적 인 룩 (? =)을 추가하거나 "no 'x'before"에 긍정적 인 룩 (? <=)을 추가 할 수 있습니다. 다음과 같이 : https://regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

이렇게하면 원하는 'x'의 정확한 수만 일치시킬 수 있습니다.


1

Enhardened의 답변을 살펴보면 두 번째 표현은 시퀀스 사이에 문자가 하나만있는 시퀀스와 일치하지 않을 것이라고 말합니다. 미리보기 / 뒤로보기를 사용하지 않고이 문제를 쉽게 수정할 수있는 방법이 있습니다. 시작 / 끝 문자를 경계 문자로 바꾸는 것입니다. 이렇게하면 시작 / 끝을 포함하는 단어 경계와 일치시킬 수 있습니다. 따라서 적절한 표현식은 다음과 같아야합니다.

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

여기에서 볼 수 있듯이 https://regex101.com/r/oC5oJ4/2 .


1
멋지다. 정규식이 경계를 어떻게 처리하는지 잘 몰랐다. 이 방법의 유일한 문제는 비표준 경계를 사용할 때입니다. 살펴보기 : regex101.com/r/j0nkeo/1regex101.com/r/4Ix7Dr/1
Enhardened

1
@Enhardened-좋은 점입니다. 여러 개의 일치하는 그룹이 겹치는 문제인 것 같습니다. 그것은 당신이 뒷모습을 사용해야 할 상황입니다.
rozza2058

1

아주 오래된 게시물이지만 도움이 될 수있는 sth를 기여하고 싶습니다. 나는 질문에 명시된 방식으로 정확하게 시도했지만 작동하지만 문제가 있습니다. 수량의 순서가 중요합니다. 이걸 고려하세요:

#[a-f0-9]{6}|#[a-f0-9]{3}

이렇게하면 16 진수 색상 코드 (3 자리 또는 6 자리 길이)가 모두 나타납니다. 근데 이렇게 뒤집 으면

#[a-f0-9]{3}|#[a-f0-9]{6}

3 자리 숫자 또는 6 자리 숫자 중 처음 3 자리 만 찾습니다. 이것은 의미가 있으며 Regex 전문가는 이것을 즉시 발견 할 수 있지만 많은 사람들에게 이것은 특이한 행동 일 수 있습니다. 순서에 관계없이이 함정을 피할 수있는 고급 Regex 기능이 있지만 모든 사람이 Regex 패턴에 깊이 빠져있는 것은 아닙니다.

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