2016년 1월 5일 화요일

정규표현식

표현식


정규표현식은 구분자라고 불리는 특수문자로 둘러싸임:
/, #, +, %, …

/foo bar/im  #im pattern modifier라고 부르며 탐색 패턴을 변경 시켜 줌. i 대소문자 구별을 없애줌. m 여러줄에 적용.

preg_match(“/php/i”, “PHP is the web scrip”, $matches);
preg_match는 PHP에서 제공하는 함수로, 첫인자로 두번째인자를 탐색. 결과를 세번째 인자에 저장.


\b 경계 문자를 검색
/\bweb\b/i  #…the web script… 처럼 독립된 ‘web’문자를 검색. ‘website’라는 단어는 검색 못함



$\$$subject = ’coding everybody http://tutorials.org egoing@egoing.com ...’
에서 url검색하면

preg_match(‘~http://\w+\.\w+~’,…)
~ 내부에 //떄문에 경계표시를 위해 /대신 사용.  \w 문자검색, + 1 이상이니 tutorials 검색.
\. . escape시켜서 .자체를 검색.



preg_match(‘~(http://\w+\.\w+)\s(\w+@\w+\.\w)~’, $\$$subject, $\$$matches);

‘\s’ 공백을 나타내고 () capturing이라고 하며 matches에 

$\$$matches[0] = “http:… com” #전체 검색 결과 저장
$\$$matches[1] = “http://tutorial.com
$\$$matches[2] = “egoing@egoing.com


배열 형태로 부분 부분 추출이 가능.



검색


preg_match('@^(?:http://)?([^/]+)@i',"http://www.php.com/indax.html", $\$$matches);

@...@ 구분자(정규표현식의 시작과 끝). i는 대소문자 동시 매칭, ^는 경계, 즉 행의 시작점을 매칭한다는 의미,

^(..)는 괄호에 있는 항으로 시작하는 행을 검색.
()안에 있는 ?:는 원래 ()가 capturing이므로 $\$$matches[1]에 값이 들어가야 하지만 그러지 말라는 의미. 'http'는 보통 따로 저장하지 않아도 됨.
?는 수량자로 0~1개이므로 "http://"가 하나 있거나 없어도 된다는 의미.
[^/]+는 /을 제외한 어떤 글자가 1개 이상 나와야 된다는 의미.

$\$$host = $\$$matches[1]가 실행되면 $\$$host에 www.php.com이 저장됨.



preg_match('/[^.]+\.[^.]+$\$$/', $\$$host, $\$$matches);

/../는 구분자. [^.]+는 .을 제외한 어떤 문자가 1개이상 나와야 함. \.는 .의 escape니까 문자 .자체를 의미함.
다시 동일한 [^.]가 나온 후, 마지막에 $\$$가 나왔으므로 $\$$는 문자의 끝에서 매칭을 한다는 의미이다.
따라서 .을 중심으로 양쪽의 두 단어를 매칭하는데 www.php가 아니라 php.com이 얻어짐.



또 다른 예를 살펴 보면,

$\$$str = 'foobar: 2008';
preg_match('/(?P<name>\w+): (?P<digit>\d+)/', $\$$str, $\$$matches);

var_dump($\$$matches)해보면

Array
{
[0] => foobar: 2008
[name] => foobar
[1] => foobar
[digit] => 2008
[2] => 2008
}

라는 출력이 나온다.


(?P<name>\w+)에서 \w+는 문자가 1개이상 나오는 것을 매칭하는데 앞부분에 ?P<name>는 연관배열 키값으로 name 키에 매칭된 문자 값 foobar를 저장하라는 의미이다.

(?P<digit>\d+)의 \d+는 숫자가 1개이상 나오는 것을 매칭하며, ?P<digit>는 digit키에 매칭된 패턴 2008을 저장.

이것은 값 표현을 명확히 하기 위해 정수인 index 대신에 연관배열의 키 값을 사용한 것으로 back reference라고 함.





치환



$\$$string = 'April 15, 2003';
$\$$pattern = '/(\w+) (\d+), (\d+)/i';
$\$$replacement = '$\$${1}1,$\$$3';
echo preg_replace($\$$pattern, $\$$replacement, $\$$string);

preg_replace는 첫번째 인자의 패턴으로 3번째 인자에서 찾고, 2번째 인자로 대치하라는 명령이다.
$\$${1}은 April, $\$$2=15, $\$$3=2003이다.

따라서 $\$$replacement=April1,2003이 된다.




$\$$string = 'The quick brown fox jumped over the lazy dog.';
$\$$patterns = array();
$\$$patterns[0] = '/quick/';
$\$$patterns[1] = '/brown/';
$\$$patterns[2] = '/fox/';
$\$$replacements = array();
$\$$replacements[2] = 'bear';
$\$$replacements[1] = 'black';
$\$$replacements[0] = 'slow';
echo preg_replace($\$$patterns, $\$$replacements, $\$$string);


$\$$replacements="The slow black bear jumped over the lazy dog"가 된다.




$\$$patterns = array ('/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/',
                   '/^\s*{(\w+)}\s*=/');
$\$$replace = array ('\3/\4/\1\2', '$\$$\1 =');

// $\$$startDate = 5/27/1999
echo preg_replace($\$$patterns, $\$$replace, '{startDate} = 1999-5-27');


패턴과 replace가 둘다 배열이다. 먼저 3번째 인자에서 pattern배열의 1번째 인자패턴을 찾아서 replace패턴의 첫번째 배열요소로 바꾼다.

19나 20을 찾음. 다음으로 숫자 2자리. -다음에 숫자 1~2자리, 다시 -다음에 숫자 1~2자리를 찾음. 따라서 "1999-5-27"이 찾아짐.

^는 맨처음, \s는 공백, *는 0~여러개, 다음에 {..}로 중괄호가 나옴. 그 사이에 문자가 1개 이상. 다음에 \s로 공백이 0~여러개 나오고 마지막에 =이다. 따라서 "{startDate} ="가 매칭된다.




References

[1] cheet key
[2] 생활코딩
[3] ZVON
[4] http://www.pyregex.com/











댓글 없음:

댓글 쓰기