Once-only subpatterns (단일 서브 패턴)
반복을 최대/최소화하면서 일치가 실패하면 반복되는 항목을 재평가하여 다른 반복 횟수로 나머지 패턴을 일치시킬 수 있는지 확인한다. 때로는 패턴의 작성자가 반복적인 일치를 수행 할 필요가 없음을 알 때는 이를 방지하거나 일치 성질을 변경하거나 다른 방법보다 먼저 실패하게하는 것이 유용하다.
예를 들어, 문자열 "123456bar"에 \d+foo
패턴을 적용하는 것을 고려해 보자.
6자리 모두를 일치한 다음 "foo"와 일치하지 않으면, 정규식의 정상적인 동작은 \d+
항목과 일치하는 5자리 숫자로 다시 시도한다. 그리고는 4자리로 다시 시도하여 궁극적으로 실패한다.
Once-only 서브 패턴은 패턴의 일부가 일치되면 이 방법으로 재평가 되지 않게하기 위해서 최초로 "foo"와의 일치가 실패 했을 경우는 즉시 포기할 것을 지정하는 수단을 제공한다. 이 표기법은 또 다른 종류의 특수 괄호로 (?>\d+)bar
와 같이 (?>
로 시작한다.
이런 종류의 괄호는 패턴이 일치하면 패턴의 일부를 잠근다("locks up"). 그리고 패턴이 더 이상의 실패하는 패턴으로 되돌아가는 것을 방지한다. 그러나 이전 항목으로 이동(Backtracking)하면 정상적으로 작동한다.
또 다른 설명은 이 유형의 서브 패턴이 문자열의 현재 위치에 고정되어 있으면 동일한 독립형 패턴이 일치하는 문자의 문자열과 일치한다는 것이다.
Once-only 서브 패턴은 서브 패턴을 캡처하지 않는다. 위의 예제와 같은 간단한 경우는 가능한 모든 것을 일치 해야하는 최대화 반복으로 생각할 수 있다. 그래서 \d+
와 \d+?
는 둘 다 나머지 패턴을 일치시키기 위해 일치하는 자릿수를 조정할 준비가되어 있다.
물론이 구조는 임의로 복잡한 서브 패턴을 포함할 수 있으며 중첩 될 수 있다.
Once-only 서브 패턴은 look-behind 어설션과 함께 사용하여 문자열 끝에 효율적인 일치를 지정한다. 일치하지 않는 긴 문자열에 적용 할 때 abcd$
와 같은 간단한 패턴을 고려하자. 매칭은 왼쪽에서 오른쪽으로 진행되기 때문에, PCRE는 대상의 각 "a"를 찾아 다음 패턴이 나머지 패턴과 일치하는지 확인한다.
패턴이 ^.*abcd$
로 지정되면 초기 .*
는 처음에는 전체 문자열과 일치한다. 그러나 이것이 실패 할 때(다음 "a"가 없기 때문에) 마지막 문자를 제외한 모든 문자와 일치하도록 역 추적하고, 마지막 문자는 제외하고 모두 반복한다. 다시 한 번 "a"에 대한 검색은 오른쪽에서 왼쪽으로 전체 문자열을 포함하므로 더 나아지지 않는다. 그러나 패턴이 ^(?>.*)(?<=abcd)
로 쓰여진 경우 .*
항목에 대해 역 추적이 불가능 할 수 있다. 그것은 전체 문자열만 일치시킬 수 있다. 후속 look-behind 어설션은 마지막 네 문자에 대해 단일 테스트를 수행한다. 실패하면 즉시 일치하지 않는다. 긴 문자열의 경우 이 접근 방식은 처리 시간에 중요한 차이를 만든다.
패턴이 무한히 반복 될 수 있는 서브 패턴 내부에 무제한 반복을 포함하는 패턴은 한 번만 서브 패턴을 사용하는 것이 매우 오랜 시간 동안 실패한 일부 일치를 피할 수 있는 유일한 방법이다. 패턴 (\D+|<\d+>)*[!?]
는 숫자가 아닌 문자 또는 <>
로 묶인 숫자 뒤에 !
또는 ?
문자가 일치하는 부분 문자열을 무제한으로 일치한다. 이 일치가 성공한다면 빠르게 실행이 완료된다. 그러나 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"에 적용되면 실패를 보고 하기까지 시간이 오래 걸린다. 이것은 문자열이 여러 가지 방법으로 두 반복 사이에서 나눌 수 있기 때문에 모두 시도해야한다. (PCRE와 Perl은 단일 문자가 사용될 때 빠른 오류를 허용하는 최적화 기능을 가지고 있기 때문에 끝에 있는 단일 문자 대신 [!?]
를 사용한다. 패턴이 ((?>\D+)|<\d+>)*[!?]
로 변경되면 일치하는데 필요한 마지막 단일 문자를 기억하고 숫자가 아닌 시퀀스는 깨질 수 없으므로 오류가 빠르게 발생한다.
- PHP 정규식(PCRE)의 모든 것 - 프롤로그
- PHP 정규식(PCRE)의 모든 것 - 구분기호(Delimiters)
- PHP 정규식(PCRE)의 모든 것 - 메타문자(Meta-characters)
- PHP 정규식(PCRE)의 모든 것 - 이스케이프 시퀀스(Escape Sequences)
- PHP 정규식(PCRE)의 모든 것 - 유니코드 문자 속성(Unicode character properties)
- PHP 정규식(PCRE)의 모든 것 - 앵커(Anchors)
- PHP 정규식(PCRE)의 모든 것 - 마침표(Dot)
- PHP 정규식(PCRE)의 모든 것 - 캐릭터 클래스(Character classes)
- PHP 정규식(PCRE)의 모든 것 - 선택(Alternation)
- PHP 정규식(PCRE)의 모든 것 - 내부 옵션 설정(Internal option setting)
- PHP 정규식(PCRE)의 모든 것 - 서브 패턴(Subpatterns)
- PHP 정규식(PCRE)의 모든 것 - 반복(Repetition)
- PHP 정규식(PCRE)의 모든 것 - 역 참조(Back references)
- PHP 정규식(PCRE)의 모든 것 - 어설션(Assertions)
- > PHP 정규식(PCRE)의 모든 것 - 일회성 서브 패턴(Once-only subpatterns)
- PHP 정규식(PCRE)의 모든 것 - 조건부 서브 패턴(Conditional subpatterns)
- PHP 정규식(PCRE)의 모든 것 - 주석(Comments)
- PHP 정규식(PCRE)의 모든 것 - 재귀 패턴(Recursive patterns)
- PHP 정규식(PCRE)의 모든 것 - 에필로그