Repetition (반복)
반복은 다음 항목 중 하나를 따를 수 있는 한정 기호로 지정된다.
일반적으로 반복 수량어는 괄호({}
) 안에 쉼표로 구분된 두 개의 숫자를 입력하여 허용되는 일치의 최소 및 최대 수를 지정한다. 숫자는 65536 보다 작아야 하며 첫 번째 숫자는 두 번째 숫자보다 작거나 같아야 한다. 예를 들어, z{2,4}
는 "zz", "zzz" 또는 "zzzz"와 일치한다.
단독으로 닫는 중괄호는 특수 문자가 아니다. 두 번째 숫자가 생략 되었으나 쉼표가 있으면 상한이 없다. 두 번째 숫자와 쉼표가 둘 다 생략되면 수량 기호는 필요한 일치 항목의 정확한 수를 지정한다. 따라서 [aeiou]{3,}
는 최소 3개의 연속 모음과 일치하지만 \d{8}
은 정확히 8자리 숫자와 일치한다. 한정 기호가 허용되지 않는 위치나 한정 기호의 구문과 일치하지 않는 위치에 나타나는 여는 중괄호({
)는 리터럴 문자로 사용된다. 예를 들어, {,6}
은 한정 기호가 아니라 4자의 리터럴 문자열이다.
한정자 {0}
이 허용되어 표현식이 이전 항목 및 한정 기호가 없는 것처럼 동작한다.
편의상 (그리고 전통적인 호환성) 세 가지 가장 일반적인 수량 기호는 한 문자로 된 단일 표현을 사용한다 :
Single-character quantifiers
문자 | 설명 |
---|---|
* |
{0,} 와 같다 |
+ |
{1,} 와 같다 |
? |
{0,1} 와 같다 |
상한이 없는 수량 기호와 일치하지 않는 서브 패턴을 따라 무한 루프를 구성 할 수 있다(예 : (a?)*
).
이전 버전의 Perl과 PCRE는 그러한 패턴을 컴파일 할 때 오류를 내기도 했다. 그러나 이 방법이 유용 할 수 있기 때문에 이러한 패턴이 이제 허용되지만 실제로 서브 패턴의 반복이 실제로 문자와 일치하지 않으면 루프가 강제로 끊어진다.
기본적으로 한정 기호는 "greedy" 즉 패턴의 나머지 부분을 실패시키지 않고 가능한 한 최대 허용 횟수까지 일치시킨다. 이것이 문제를 일으키는 곳의 고전적인 예는 C 프로그램의 주석과 일치하는 것이다. 시퀀스 /*
와 */
사이에 나타나며 시퀀스 내에서 개별 *
및 /
문자가 나타날 수 있다. 첫 번째 주석 */
주석 /*
두 번째 주석 */
에 문자열 /**.*\*/
패턴을 적용하여 C 주석을 일치 시키려는 시도는 .*
의 탐욕("greedy")으로 인해 전체 문자열과 일치하기 때문에 실패한다.
그러나 수량 기호 다음에 물음표가 오는 경우에는 게으르며(lazy) 가능한 최소 횟수와 일치하므로 패턴 /\*.*?\*/
는 C 주석과 함께 올바른 작업을 수행한다. 다양한 한정어의 의미는 다른 방식으로 변경되지 않으며 선호하는 일치 개수만 변경된다. 이 ?
사용을 그 자체로 한정 기호로 사용하는 것과 혼동하지 말아야 한다. 두 가지 용도로 사용되기 때문에 \d??\d
와 같이 두 글자로 표시되는 경우가 있다. 한 글자가 기본 설정과 일치하지만 나머지 패턴 일치하는 경우 두 글자와 일치할 수 있다.
PCRE_UNGREEDY 옵션이 설정되어 있으면 (Perl에서는 사용할 수없는 옵션) 수량 한정자는 기본적으로 탐욕(greedy)이 없다. 하지만 개별적인 물음표는 물음표를 따라 가면서 탐욕이 적용된다. 즉, 기본 동작을 반전한다.
+
를 따르는 한정 기호는 "possessive"이다. 가능한 한 많은 문자와 일치하고 나머지 패턴과 일치하도록 돌아가지 않는다. 따라서 .*abc
는 "aabc"와 일치하지만 .*+
는 전체 문자와 일치하기 때문에 .*+abc
는 일치하지 않는다. Possessive 지정자는 처리 속도를 높이는 데 사용할 수 있다.
<?php
$str = 'aabc';
preg_match('/.*abc/', $str, $matches);
print_r($matches);
// Array
// (
// [0] => aabc
// )
preg_match('/.*+abc/', $str, $matches);
print_r($matches);
// Array
// (
// )
괄호로 둘러싼 서브 패턴이 2 이상의 최소 반복이나 최대 제한을 가지면, 컴파일한 패턴은 최소 / 최대의 크기에 따라서 더 많은 공간이 필요하다.
패턴이 .*
또는 .{0,}
으로 시작하고 PCRE_DOTALL 옵션(Perl의 /s
와 동일)이 설정되어 .
이 개행 문자와도 일치하게 되면 패턴은 암시적으로 고정된다. 왜냐하면 뒤에 오는 것은 문자열의 모든 문자 위치에 대해 시도된다. 따라서 첫 번째 이후의 모든 위치에서 전체 일치를 다시 시도할 필요가 없다. PCRE(Perl Compatible Regular Expressions)는 앞에 \A
가 붙은 것처럼 패턴을 취급한다. 대상 문자열에 개행 문자가 없는 것을 알 경우, 최적화를 위해 .*
로 시작하는 패턴에 PCRE_DOTALL을 설정하거나 ^
를 사용하여 명시적으로 고정을 나타낼 수 있다.
캡처 서브 패턴이 반복되면 캡처된 문자열은 마지막 반복에 일치한다. 예를 들어, (tweedle[dume]{3}\s*)+
가 "tweedledum tweedledee"와 일치하면 캡처된 부분 문자열의 값은 "tweedledee"이다. 그러나 중첩된 캡처 서브 패턴이 있으면 해당 캡처 값이 이전 반복에서 설정 되었을 수 있다. 예를 들어, /(a|(b))+/
가 "aba"와 일치하면 두 번째로 캡처된 하위 문자열의 값은 "b"가 된다.
<?php
preg_match('/(tweedle[dume]{3}\s*)+/', 'tweedledum tweedledee', $matches);
print_r($matches);
// Array
// (
// [0] => tweedledum tweedledee
// [1] => tweedledee
// )
preg_match('/(a|(b))+/', 'aba', $matches);
print_r($matches);
// Array
// (
// [0] => aba
// [1] => a
// [2] => b
// )
- 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)의 모든 것 - 에필로그