profile

이 세상에 하나는 남기고 가자

세상에 필요한 소스코드 한줄 남기고 가자

PHP 정규식(PCRE)의 모든 것 - 조건부 서브 패턴(Conditional subpatterns)

유영재

Conditional subpatterns (조건부 서브 패턴)

조건부로 서브 패턴을 따르거나 어설션의 결과에 따라 두 개의 대체 서브 패턴 중 하나를 선택하거나 이전 캡처 서브 패턴이 일치하는지 여부를 결정할 수 있다. 조건부 서브 패턴의 가능한 두 가지 형태는 다음과 같다.

(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)

조건이 충족되면 "yes-pattern"이 사용된다. 그렇지 않으면 "no-pattern"(존재한다면)이 사용된다. 서브 패턴에 두 개 이상의 선택이 있는 경우 컴파일 타임 오류가 발생한다.

아래에 두 가지 종류의 조건이 있다.

괄호 사이의 텍스트가 일련의 숫자로 구성되어 있으면 해당 숫자의 캡처 서브 패턴이 이전에 일치 한 경우 조건이 충족된다. 읽기 쉽도록 하기 위해 의미 없는 공백을 포함해서 세 부분으로 나눈 다음 패턴을 고려해 보자(PCRE_EXTENDED 옵션을 가정).

( \( )? [^()]+ (?(1) \) )

  • 첫 번째 부분은 선택적 여는 괄호와 일치하며, 해당 문자가 있는 경우 첫 번째 부분 문자열로 설정한다.
  • 두 번째 부분은 괄호가 아닌 하나 이상의 문자와 일치한다.
  • 세 번째 파트는 첫 번째 괄호 세트가 일치하는지 여부를 테스트하는 조건부 서브 패턴이다.

만약 그렇다면, 즉, 시작 괄호로 시작한 문자열은 조건이 참이므로 "yes-pattern"이 실행되고 닫는 괄호가 필요하다. 그렇지 않으면 "no-pattern"이 없으므로 서브 패턴은 아무것도 일치하지 않는다. 즉, 이 패턴은 괄호 안에 괄호로 묶지 않은 비괄호의 시퀀스와 일치한다.

조건이 문자열 "(R)" 인 경우 패턴 또는 서브 패턴에 대한 재귀 호출이 수행되면 만족된다. "top level"에서 조건은 거짓이다.

조건이 일련의 숫자나 "(R)"이 아닌 경우 조건이 어설션이어야 한다. 이것은 positive 또는 negative lookahead 또는 lookbehind assertion 일 수 있다. 중요하지 않은 공백을 포함하는 이 패턴을 고려하고 두 번째 줄에 있는 두 가지 선택을 고려하자.

(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2}  |  \d{2}-\d{2}-\d{2} )

조건은 비문자와 문자가 뒤에 붙는 선택적 순서와 일치하는 positive lookahead이다. 즉, 문자열에 적어도 하나의 문자가 있는지 테스트 한다. 문자가 발견되면, 첫 번째 선택에 대해 대상이 대조된다. 그렇지 않으면 두 번째와 일치한다. 이 패턴은 두 형식 "dd-aaa-dd" 또는 "dd-dd-dd" 중 하나의 문자열을 일치시킨다. 여기서 "aaa"는 문자이고 "dd"는 숫자다.


comments powered by Disqus