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

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

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

PHP 정규식(PCRE)의 모든 것 - 내부 옵션 설정(Internal option setting)

유영재

Internal option setting (내부 옵션 설정)

PHP 정규표현식 패턴에 존재하는 변경자와 유사하게 사용되나 사용 위치가 다르다.

PCRE_CASELESS, PCRE_MULTILINE,PCRE_DOTALL, PCRE_UNGREEDY, PCRE_EXTRA, PCRE_EXTENDED 및 PCRE_DUPNAMES의 설정은 "(?" 및 ")"로 묶인 Perl 옵션 문자 시퀀스에 의해 패턴 내에서 변경할 수 있다.

옵션 문자는 다음과 같다.

Internal option letters(내부 옵션 문자)

옵션 설명
i PCRE_CASELESS
m PCRE_MULTILINE
s PCRE_DOTALL
x PCRE_EXTENDED
U PCRE_UNGREEDY
X PCRE_EXTRA
J PCRE_INFO_JCHANGED

예를 들어, (?im)은 대소문자를 구분하지 않고(caseless) 여러 줄 일치를 설정한다. 문자 앞에 하이픈을 붙여 이러한 옵션의 설정을 해제 할 수도 있다. (?im-sx)를 지정하면, PPCRE_DOTALLPCRE_EXTENDED 설정을 해제 하면서 PCRE_CASELESSPCRE_MULTILINE을 설정한다. 하이픈 앞과 뒤 모두에 옵션이 나타나면 옵션을 해제한다.

옵션 변경이 최상위 레벨에서 발생하면(즉, 서브 패턴 괄호 밖에 있는 경우), 변경 사항은 뒤 따르는 패턴의 나머지 부분에 적용된다. 그래서 /ab(?i)c/는 "abc"와 "abC"에만 일치한다(이 작동은 PCRE 4.0에서 변경되었으며, PHP 4.3.3부터 포함되었다).

서브 패턴 내에서 옵션 변경이 발생하면 효과가 달라진다. 이것은 Perl 5.005에서 동작이 변경된 부분이다. 서브 패턴 내부의 옵션 변경은 그 뒤에 오는 서브 패턴의 해당 부분에만 영향을 미치므로 a(?i)b)c는 abc 및 aBc와 일치하며 다른 문자열은 없다 (PCRE_CASELESS가 사용되지 않는다고 가정).

이 방법을 사용하면 패턴의 다른 부분에서 옵션을 다르게 설정할 수 있다. 하나의 선택에서 변경한 사항은 동일한 서브 패턴 내에서 지속적으로 사용된다. 예를 들어 (a(?i)b|c)는 "ab", "aB", "c"및 "C"와 일치한다. "C"는 옵션을 설정하기 전에 나누어진 분기에 해당하지만, 이상한 동작일지라도, 처리 시에 옵션 설정의 효율성을 위해서 일치한다.

PCRE 전용 옵션 PCRE_UNGREEDYPCRE_EXTRA는 각각 UX 문자를 사용하여 Perl 호환 옵션과 동일한 방식으로 변경할 수 있다. (?X) 플래그 설정은 최상위 레벨에서 활성화 되는 추가 기능보다 항상 먼저 실행되어야 하는 점에서 특별하다. 따라서 시작 부분에 넣는 것이 가장 좋다.

<?php
// PCRE_EXTRA   (?X)    Strict escape parsing

echo (preg_match('/\y/', 'abc\ydef') ? 'true' : 'false') . "\n";
// true

echo (preg_match('/\y/X', 'abc\ydef') ? 'true' : 'false') . "\n";
// Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset 1 in _test.php on line 7
// false

echo (preg_match('/\\\\y/X', 'abc\ydef') ? 'true' : 'false') . "\n";
// true

echo (preg_match('/(?X)\ydef/', 'abc\ydef') ? 'true' : 'false') . "\n";
// Warning: preg_match(): Compilation failed: unrecognized character follows \ at offset 5 in _test.php on line 14
// false

echo (preg_match('/(?X)\\\\ydef/', 'abc\ydef') ? 'true' : 'false') . "\n";
// true

echo (preg_match('/\y(?X)def/', 'abc\ydef') ? 'true' : 'false') . "\n";
// true

comments powered by Disqus