정규표현식 의 핵심. 패턴변경자 1

· 2013-02-04 (월) 17:41:10 · 7131 · 20
대단할것은 없는 강좌이지만,
제 강좌를 출처를 밝히고 외부로 퍼가는 것은 허용하지만,
다른 강좌의 자료나 책의 자료로 사용되거나 부분적인 인용은 허용하지 않습니다.

강좌는 php 5. 대를 기준으로 하며, PCRE (펄과 호환 되는 정규표현식)을 다룹니다.
PCRE 는 preg_ 로 시작되는 내장함수와 함께 사용되어지는 정규표현식을 말합니다.

PCRE > 정규표현식 의 핵심. 패턴변경자 1

이전 내용에서는 정규표현식의 메타문자에 대해서 알아보았습니다.
이번 내용에서도 역시 정규표현식의 핵심이라고 볼수 있는 패턴변경자에 대해서 이어서 알아보도록 하겠습니다.

패턴변경자란?
쉽게 설명하자면, 복잡해질수 있는 패턴을 쉽게 표현 가능하도록 해주는 것입니다.

1. i
이것은 주어진 패턴으로 문자열을 검사하되 대소문자는 구별하지 않겠다 는 것입니다.

즉, /^[a-z]+$/ 이렇게 사용한다면, 알파벳 소문자로만 이루어진 문자열을 찾는것이고
/^[a-z]+$/i 와 같이 사용한다면, /^[a-zA-Z]+$/ 와 같은 방법인 대소문자 구분없이 알파벳으로 이루어진 문자열을 찾는것입니다.

예제18> test18.php

<?php

$string = "zOOzoOZOozooZooZOO";

$patterns = Array();
$patterns[] = "/[a-z]{3}/"// 연속된 알파벳 소문자 세자를 찾는 패턴
$patterns[] = "/[A-Z]{3}/"// 연속된 알파벳 대문자 세자를 찾는 패턴
$patterns[] = "/[a-zA-Z]{3}/"//대소문자 구분없이 연속된 알파벳 대문자 세자를 찾는 패턴
$patterns[] = "/[a-z]{3}/i"// i 패턴 변경자를 사용하여 대소문자 구분없이 연속된 알파벳 세자를 찾는 패턴
$patterns[] = "/[A-Z]{3}/i"// i 패턴 변경자를 사용하여 대소문자 구분없이 연속된 알파벳 세자를 찾는 패턴

$patterns[] = "/zoo/"// zoo 를 찾는 패턴
$patterns[] = "/ZOO/"// ZOO 를 찾는 패턴
$patterns[] = "/[zZ][oO][oO]/"//대소문자 구분없이 zoo 를 찾는 패턴
$patterns[] = "/zoo/i"// i 패턴 변경자를 사용하여 대소문자 구분없이 zoo 를 찾는 패턴
$patterns[] = "/ZOO/i" // i 패턴 변경자를 사용하여 대소문자 구분없이 zoo 를 찾는 패턴

foreach($patterns as $pattern){

    if (preg_match($pattern, $string, $m)) {

        echo '<font color="blue">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함한 문자열 입니다. <br>" . $m[0] . "</font><br /><br />" . PHP_EOL;
    }
    else {

        echo '<font color="red">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.</font><br /><br />" . PHP_EOL;
    }
}

?>


결과 :

/[a-z]{3}/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
ozo

/[A-Z]{3}/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
OZO

/[a-zA-Z]{3}/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO

/[a-z]{3}/i ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO

/[A-Z]{3}/i ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO

/zoo/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zoo

/ZOO/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
ZOO

/[zZ][oO][oO]/ ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO

/zoo/i ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO

/ZOO/i ==> zOOzoOZOozooZooZOO 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
zOO



2. s
이것은 패턴 내의 . 메타 문자에 대하여 \n(개행문자) 를 포함하겠다 는 뜻입니다.
이전 내용에서 . 메타 문자아무 문자나 하나 를 가리킨다고 하였습니다.
그러나, 이것을 좀 더 정확히 표현하자면 \n(개행문자) 를 제외한 모든 문자중 하나 입니다.
즉, . 메타문자에 \n 도 포함하여 사용할려면 s 패턴변경자와 같이 쓰여져야 합니다.

예제19> test19.php

<?php

$string = "I am a boy.
You are a girl?";

$patterns = Array();
$patterns[] = "/^.+/"// \n 을 제외한 모든 문자를 찾는다.
$patterns[] = "/^.+/s"// s 패턴 변경자를 사용하여 \n 을 포함한 모든 문자를 찾는다.
$patterns[] = "/^[^!]+/"// !를 제회한 모든 문자를 찾는다.
$patterns[] = "/^.+$/"// \n 을 제외한 모든 문자를 찾는다.
$patterns[] = "/^.+$/s"// s 패턴 변경자를 사용하여 \n 을 포함한 모든 문자를 찾는다.
$patterns[] = "/^[^!]+$/"// !를 제회한 모든 문자를 찾는다.

foreach($patterns as $pattern){

    if (preg_match($pattern, $string, $m)) {

        echo '<font color="blue">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함한 문자열 입니다. <br> " . nl2br($m[0]) . "</font><br /><br />" . PHP_EOL;
    }
    else {

        echo '<font color="red">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.</font><br /><br />" . PHP_EOL;
    }
}

?>


결과 :

/^.+/ ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.


/^.+/s ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?

/^[^!]+/ ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?

/^.+$/ ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^.+$/s ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?

/^[^!]+$/ ==> I am a boy.You are a girl? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?

※ 예제 결과에서 첫번째 결과와 네번째 결과를 비교해 보면 패턴은 각각 /^.+/ /^.+$/ 입니다.
그런데, 첫번째는 결과가 있고, 두번째는 결과가 없습니다.
패턴의 차이는 $ 가 붙었나 안 붙었나의 차이입니다.
즉, 이것은 s 패턴변경자가 없기 때문에 . 메타문자는 \n 을 포함하지 않습니다.
따라서 원래의 문자열에 \n 이 포함되어있기 때문에 $ 가 붙으면 끝까지 일치 하는 것이므로 네번째는 결과가 없는 것입니다.

/^[^!]+/ 이 패턴을 예제에 넣은 이유는 . 메타문자와 ^ 과 함께 사용되는 문자클래스를 비교 하기 위함입니다.
. 은 s 패턴변경자에 따라 \n 문자를 포함하지만, ^ 과 함께 사용된 문자클래스는 지정된 문자를 제외한 모든 문자이므로
문자클래스에 \n을 포함하지 않았다면 당연히 \n 을 포함하여 검사합니다.



3. m
이것은 주어진 문자열을 여러줄로 취급 하여 검사 하겠다 는 것입니다.
문자열의 시작을 나타내는 ^ 나 문자열의 끝을 나타내는 $ 와 같이 사용될때만 의미 가 있습니다.
즉, ^ 과 $의 의미가 변하게 됩니다.
^ 은 전체 문자열의 시작을 의미하지 않고 줄(line)의 시작 을 의미합니다.
반대로 $ 은 전체 문자열의 끝을 의미하지 않고 줄(line)의 끝 을 의미합니다.

m 패턴변경자를 사용하지 않았다면 주어진 문자열이 여러줄이라도 한줄로 취급합니다.
즉, \n (개행문자) 를 하나의 문자로 취급한다는 것이지 줄바꿈을 해주는 개행문자로 취급하지 않는다는 뜻 이기도 합니다.


예제20> test20.php

<?php

$string = "I am a boy.
You are a girl?
I am a student.
You are a student too?";

$patterns = Array();
$patterns[] = "/^I.+$/"// 첫글자가 I 인것을 찾는다.
$patterns[] = "/^Y.+$/"// 첫글자가 Y 인것을 찾는다.
$patterns[] = "/^I.+$/s"// s 패턴 변경자를 사용하여 첫글자가 I 인것을 찾는다.
$patterns[] = "/^Y.+$/s"// s 패턴 변경자를 사용하여 첫글자가 Y 인것을 찾는다.
$patterns[] = "/^I.+$/m"// m 패턴 변경자를 사용 하여 첫글자가 I인것을 찾는다.
$patterns[] = "/^Y.+$/m"// m 패턴 변경자를 사용 하여 첫글자가 Y인것을 찾는다.
$patterns[] = "/^I.+$/ms"// m 과 s 패턴 변경자를 사용 하여 첫글자가 I인것을 찾는다.
$patterns[] = "/^Y.+$/ms" ; // m 과 s 패턴 변경자를 사용 하여 첫글자가 Y인것을 찾는다.
$patterns[] = "/^I.+/"// 첫글자가 I 인것을 찾는다.
$patterns[] = "/^Y.+/"// 첫글자가 Y 인것을 찾는다.
$patterns[] = "/^I.+/s" ; // s 패턴 변경자를 사용하여 첫글자가 I 인것을 찾는다.
$patterns[] = "/^Y.+/s"// s 패턴 변경자를 사용하여 첫글자가 Y 인것을 찾는다.
$patterns[] = "/^I.+/m"// m 패턴 변경자를 사용 하여 첫글자가 I인것을 찾는다.
$patterns[] = "/^Y.+/m"// m 패턴 변경자를 사용 하여 첫글자가 Y인것을 찾는다.
$patterns[] = "/^I.+/ms" // m 과 s 패턴 변경자를 사용 하여 첫글자가 I인것을 찾는다.
$patterns[] = "/^Y.+/ms"// m 과 s 패턴 변경자를 사용 하여 첫글자가 Y인것을 찾는다.

foreach($patterns as $pattern){

    if (preg_match($pattern, $string, $m)) {

        echo '<font color="blue">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.<br>" . nl2br($m[0]) . "</font><br /><br />" . PHP_EOL;
    }
    else {

        echo '<font color="red">' . htmlspecialchars($pattern) . ' ==> ' . $string . " 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.</font><br /><br />" . PHP_EOL;
    }
}

?>


결과 :

/^I.+$/ ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^Y.+$/ ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^I.+$/s ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?
I am a student.
You are a student too?

/^Y.+$/s ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^I.+$/m ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.


/^Y.+$/m ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
You are a girl?


/^I.+$/ms ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?
I am a student.
You are a student too?

/^Y.+$/ms ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
You are a girl?
I am a student.
You are a student too?

/^I.+/ ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.


/^Y.+/ ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^I.+/s ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?
I am a student.
You are a student too?

/^Y.+/s ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함하지 않은 문자열 입니다.

/^I.+/m ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.


/^Y.+/m ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
You are a girl?


/^I.+/ms ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
I am a boy.
You are a girl?
I am a student.
You are a student too?

/^Y.+/ms ==> I am a boy.You are a girl?I am a student.You are a student too? 은 패턴에 매치되는 문자열을 포함한 문자열 입니다.
You are a girl?
I am a student.
You are a student too?

※ 첫번째 /^I.+$/ 패턴은 대문자 I 로 시작하면서 \n을 제외한 모든 문자로만 끝까지 이루어진 문자열을 매치 합니다.
따라서 주어진 문자열에는 \n 이 포함되어 있으므로 매치된 결과가 없는 것입니다.

두번째 /^Y.+$/ 패턴은 대문자 Y 로 시작하는 것을 찾는것을 제외하면 첫번째 패턴과 동일합니다.

다섯번째 /^I.+$/m 패턴은 m 패턴변경자를 사용함 으로써 ^ 과 $ 이 줄의 시작과 끝 을 가리키게 되므로 I am a boy. 가 매치되었습니다.

일곱번째 /^I.+$/ms 패턴은 m 과 s 패턴변경자 두개를 동시에 사용 하였습니다.
의미가 다른 패턴 변경자는 여러개를 동시에 사용할수 있습니다.
그런데, 여기서 보면 m 패턴변경자를 사용하였으므로 $ 은 줄의 끝을 가리키는 것인데, 결과값은 4줄 모두 나왔습니다.
그 이유는 정규표현식은 매치되는 문자열을, 최대로 매치되는 범위 모두를 잡기 때문에 그렇습니다.
s 패턴 변경자를 사용하였기 때문에 \n 도 . 메타문자에 포함되고 맨끝도 라인의 끝이 되므로 모두 매치되는 것입니다.

아홉번째 이하는 $ 의 있고 없고의 차이를 보여주기 위한 예제입니다.
|

댓글 20개

2013-02-04 (월) 17:44:20
잘보겠습니다 꾸벅
네 감사합니다. 일번이네요.
좋아요 좋아요
고맙습니다.
시간은 없고, 일단 찜해두자는 의미에서 추천만......ㅎ
음~ 크롬에서는 추천이 안되는군요... 다시 익스로 들어와서 추천!!
고맙습니다. 도레미님.
2013-02-04 (월) 20:07:48
감사합니다.~
어 그래 고맙다.
2013-02-05 (화) 14:09:08
ㅎㅎㅎㅎㅎ
2013-02-04 (월) 23:51:01
잘 봤습니다...
항상 챙겨 봐 줘서 고맙습니다.
쉽게 잘 설명해 주셨네요. 나린위키 파서 만들때 정규 표현식땜에 고생좀 했었는데.. 새록새록 기억이 다시 납니다 ^^
네에 고맙습니다.

예전에 깊게는 못보고 언뜻 나린위키 파서를 훓어 본거 같은데.
아주 잘 만들었던 것 같습니다.
/m 은 처음 알게 되었네요.
2라인 이상일 때 시작(^), 종료($) 메타 문자의 범위를
현재 라인에서 전체 라인으로 범위를 확대해주는 역활이군요.

잘 봤습니다.
네에
말씀 하신 것과 반대의 의미 입니다.
m 을 사용하게 되면
^ 은 라인의 시작
$ 은 라인의 끝을 의미 합니다.

좋게 봐주셔서 감사합니다.
한동안 강좌가 올라오지 않아서 끝났나 했더니 다시 시작됐네요.
감사합니다.
개인적인 사정으로
제가 시간 날때 한번씩 올립니다.
감사합니다.
2013-03-10 (일) 01:45:13
패턴변경자는 i 밖에 몰랐는데 s 랑 m 도 있다는걸 배웠네요..
좋은강좌 감사합니다 ^^
아직 패턴변경자 1이라서 세개만 설명했습니다.

나중에 패턴변경자 2가 있습니다.
수고하셨습니다.
댓글을 작성하시려면 로그인이 필요합니다.

프로그램

8,188건
+
제목 글쓴이 날짜 조회
13-02-18 조회 3,515
13-02-15 조회 3,931
13-02-12 조회 5,776
13-02-04 조회 4,078
13-01-30 조회 4,935
13-01-25 조회 3,686
13-01-18 조회 3,756
13-01-18 조회 5,491
13-01-18 조회 6,119
13-01-18 조회 3,779
13-01-18 조회 4,731
13-01-17 조회 4,063
13-01-17 조회 3,562
13-01-17 조회 3,622
13-01-17 조회 3,965
12-12-31 조회 3,542
12-12-28 조회 4,899
12-12-28 조회 5,958
12-12-28 조회 3,400
12-12-27 조회 3,578
12-12-27 조회 4,282
12-12-20 조회 5,201
12-12-18 조회 9,066
12-12-14 조회 4,887
12-12-10 조회 3,627
12-12-10 조회 3,098
12-12-01 조회 3,807
12-11-25 조회 7,275
12-11-22 조회 5,914
12-11-20 조회 2.4만
12-11-19 조회 4,311
12-11-13 조회 3,857
12-11-12 조회 3,864
12-10-23 조회 4,698
12-09-25 조회 4,336
12-09-05 조회 6,935
12-09-04 조회 7,494
12-09-04 조회 3,415
12-08-30 조회 3,382
12-08-30 조회 3,597
12-08-29 조회 3,331
12-08-29 조회 3,149
12-08-26 조회 3,456
12-08-18 조회 3,702
12-08-17 조회 3,980
12-08-16 조회 3,530
12-08-14 조회 3,178
12-08-13 조회 5,584
12-08-13 조회 3,342
12-08-11 조회 3,620
12-08-10 조회 3,197
12-08-07 조회 3,957
12-08-07 조회 3,190
12-08-06 조회 3,405
12-07-31 조회 3,168
12-07-30 조회 3,490
12-07-30 조회 3,122
12-07-29 조회 3,299
12-07-29 조회 3,050
12-07-27 조회 3,105
12-07-21 조회 2,977
12-07-19 조회 3,182
12-07-19 조회 2,769
12-07-17 조회 3,404
12-07-17 조회 3,032
12-07-17 조회 3,941
12-07-16 조회 2,977
12-07-15 조회 3,097
12-07-14 조회 3,149
12-07-13 조회 8,235
12-07-11 조회 3,378
12-07-10 조회 9,946
12-07-09 조회 3,156
12-07-08 조회 4,341
12-07-06 조회 3,625
12-07-05 조회 3,908
12-07-05 조회 3,325
12-07-05 조회 3,195
12-07-03 조회 3,221
12-07-03 조회 3,163
12-07-02 조회 3,199
12-07-02 조회 2,824
12-06-30 조회 3,428
12-06-26 조회 3,137
12-06-22 조회 3,179
12-06-22 조회 3,124
12-06-21 조회 3,101
12-06-21 조회 3,321
12-06-20 조회 3,489
12-06-20 조회 3,160
12-06-20 조회 3,067
12-06-18 조회 3,945
12-06-17 조회 3,378
12-06-15 조회 3,000
12-06-14 조회 2,893
12-06-13 조회 3,502
12-06-11 조회 3,322
12-06-08 조회 3,291
12-06-06 조회 3,148
12-06-06 조회 3,547