정규식에서 대괄호와 괄호의 차이점은 무엇입니까?


101

다음은 JavaScript에서 사용하기 위해 만든 정규식입니다.

var reg_num = /^(7|8|9)\d{9}$/

다음은 팀원이 제안한 또 다른 것입니다.

var reg_num = /^[7|8|9][\d]{9}$/

규칙은 전화 번호를 확인하는 것입니다.

  • 10 개의 숫자 여야합니다.
  • 첫 번째 숫자는 7, 8 또는 9입니다.

답변:


124

다음 정규식은 동일합니다 (일치 목적을 위해).

  • /^(7|8|9)\d{9}$/
  • /^[789]\d{9}$/
  • /^[7-9]\d{9}$/

설명:

  • (a|b|c)은 정규식 "OR"이며 "a 또는 b 또는 c"를 의미합니다. OR에 필요한 대괄호가 있으면 숫자 도 캡처 됩니다. 엄격히 동일하게하려면 캡처 그룹 (?:7|8|9)으로 만들도록 코딩 해야합니다 .

  • [abc]는 "a, b 또는 c의 모든 문자"를 의미하는 "문자 클래스"입니다 (문자 클래스는 범위를 사용할 수 있습니다 (예 : [a-d]= [abcd]).)

이러한 정규식이 유사한 이유는 문자 클래스가 "or"(단일 문자에만 해당)의 속기이기 때문입니다. 교대 (abc|def)로 문자 클래스로 변환되지 않는 것과 같은 작업을 수행 할 수도 있습니다 .


30
(7|8|9)[789]상기 제 후자하지 캡처하기 때문에, 동등하지 않다. (?:7|8|9)다른 한편으로는 동등 할 것입니다 (물론 당신이 그것을 알고 있다고 생각합니다 ...).
hochl

이 정규식을보고 있습니다 : [<<|>>|\]\]|\[\[]. 컨텍스트 때문에 정규식이 <<또는 >>또는 [[또는 일치하려고한다는 것을 알고 ]]있습니다. 그러나 당신이 말한 것에서 일치하는 <or >or [or ]. |between 을 사용 []하면 대괄호가 다르게 작동합니까?
Daniel Kaplan

1
@DanielKaplan은 파이프 문자 자체와 일치하지 않는 |한 문자 클래스 내에서 사용하지 마십시오 [...]. 또한 문자 클래스에서 문자를 복제해도 효과가 없습니다. 문자 클래스는 문자 목록이며 그중 하나와 정확히 일치합니다. 내 생각 엔 일반적인 둥근 대괄호를 사용 하는 그룹 을 원한다는 것입니다 .(<<|>>|\]\]|\[\[)
Bohemian

57

실수를 제외하고 는 팀의 조언이 거의 맞습니다. 그 이유를 알게되면 절대 잊지 못할 것입니다. 이 실수를보세요.

/^(7|8|9)\d{9}$/

이것이하는 일 :

  • ^그리고 $이러한 앵커 사이의 서브 패턴이 전체 일치하는 것을 주장하는 고정 된 일치를 의미한다. 문자열은 하위 패턴이 섹션뿐만 아니라 전체와 일치하는 경우에만 일치합니다.
  • ()캡처 그룹을 나타냅니다 .
  • 7|8|9중 하나와 일치하는 의미 7, 8또는 9. 또한 이것을 수행 교대 파이프 조작자가 무엇 인 |번갈아 교대 사이 - 않는다. 이것은 교대 사이를 역 추적합니다. 첫 번째 교대가 일치하지 않으면 엔진은 교대 일치 중에 포인터 위치가 이동하기 전에 돌아와 다음 교대를 계속 일치시켜야합니다. 캐릭터 클래스는 순차적으로 진행할 수 있습니다 . 최적화가 비활성화 된 정규식 엔진에서이 일치를 확인하십시오.
Pattern: (r|f)at
Match string: carat

교대

Pattern: [rf]at
Match string: carat

수업

  • \d{9}9 자리 숫자와 일치합니다. \d임의의 숫자와 일치하는 속기 메타 문자입니다.
/^[7|8|9][\d]{9}$/

그것이 무엇을하는지보십시오 :

  • ^$뿐만 아니라 고정 된 일치를 의미한다.
  • [7|8|9]A는 문자 클래스는 . 목록에서 모든 문자는 7, |, 8, |, 또는 9따라서이 일치시킬 수 |잘못에서 추가되었다. 역 추적없이 일치합니다.
  • [\d]메타 문자에 서식하는 문자 클래스입니다 \d. 문자 클래스와 단일 메타 문자의 조합은 추상 계층이 일치 속도를 늦출 수 있기 때문에 나쁜 생각이지만 이것은 구현 세부 사항 일 뿐이며 일부 정규식 구현에만 적용됩니다. JavaScript는 하나가 아니지만 하위 패턴을 약간 더 길게 만듭니다.
  • {9} 이전 단일 구성이 총 9 번 반복됨을 나타냅니다.

최적의 정규식은입니다 /^[789]\d{9}$/. /^(7|8|9)\d{9}$/불필요한 캡처는 대부분의 정규식 구현에서 성능 저하를 초래하기 때문입니다 (질문 var이 코드에서 키워드 를 사용한다는 점을 고려하면 아마도 JavaScript 일 것입니다.) 사용프리그 매칭을 위해 PCRE에서 실행되는 것은 역 추적의 부족을 최적화 할 것입니다. 그러나 우리는 PHP에도 없습니다. 따라서 []교대 대신 클래스 를 사용 |하면 매치가 역 추적되지 않기 때문에 성능 보너스를 제공하므로 둘 다 사용하는 것보다 더 빨리 이전 정규식.


6
관심이 없는데, 그 스크린 샷은 어떤 프로그램에서 나왔나요?
미스터 미스터리 고객

12

처음 두 개의 예는 무언가로 대체하는 경우 매우 다르게 작동합니다. 이것에 일치하는 경우 :

str = str.replace(/^(7|8|9)/ig,''); 

7 또는 8 또는 9를 빈 문자열로 바꿉니다.

이것에 일치하면

str = str.replace(/^[7|8|9]/ig,''); 

당신은 7또는 8또는 9또는 수직 막대를 교체 할 것입니다 !!!! 빈 문자열로.

나는 이것을 어려운 방법으로 발견했습니다.


6
SO에 오신 것을 환영합니다! 교체하거나 일치하는 것은 명백한 잘못입니다. 많은 사람들이 이러한 실수를 저지르고, 입력 문자열에 파이프 ( |) 가 포함되지 않았기 때문에 일반적으로 몇 년 동안, 때로는 실수로 피합니다 .
Alan Moore
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.