본문 바로가기
study/TIP

정규식

by 휘루걸음 2010. 12. 10.
728x90
반응형
반응형
728x90

 

정규식 사용법

Dev Web/PHP Dev 2006/04/20 04:10
 정규 표현식의 규칙 문자열 패턴을 표현하기 위해 정규 표현식 함수와 함께 사용되는 특수 문자들이 있다. 정규표현식에 사용되는 이 특수 문자들의 사용법을 먼저 알아보도록 하자.

패턴 표현에 사용되는 특수 문자
정규 표현식에서 패턴을 표현하기 위해 사용하는 특수 문자와 규칙은 다음과 같다.

1. '.' 특수 문자 '.'은 어떤 문자이건 간에 임의의 한 글자를 나타낸다. 예를 들면, 패턴 a.c는 어느 한문자의 앞 문자가 a이고 뒷 문자는 c인 모든 문자열을 포함한다. 따라서 aac나 abc,acc는 이 패턴에 일치되는 문자열이다. 그러나 .은 반드시 임의의 한 글자만을 대신하기 때문에 a로 시작해 c로 끝나는 문자열 중 두 글 자뿐인 ac나 abbc 등은 이 패턴에 포함되지 않는다.

사용예 내  용 해당문자열
s.e s와 e 사이에 임의의 한 글자를 갖는 문자열과 일치한다. sae, sbe, sce, sde...
.ce ce 앞에 임의의 한 글자를 갖는 문자열과 일치한다. ace, kce, ffce...

2. '*' 특수 문자 '*'는 바로 앞의 문자를 의미하며 그 문자가 없거나 하나 이상임을 나타낸다. 위의 '.'이 그 자체로 임의의 한 글자만을 의미하는 데 반해 '*'는 바로 복수 개의 문자를 나타낼 수 있다. 대신 '*' 앞에는 반드시 문자가 하나 이상 있어야 한다. 만일 "*e"와 같이 '*' 앞에 문자가 없으면 잘못된 패턴으로 인식해 에러가 발생한다.

 

사용예 내  용 해당문자열
s*e e 앞에 s가 없거나 하나 이상 존재하는 모든 문자열을 나타낸다. e, se, sse, ssse....
abc* ab 다음에 c가 없거나 하나 이상 존재하는 모든 문자열을 나타낸다. ab, abc, abcc, abccc...
h*im im 앞에 h가 없거나 하나 이상 존재하는 모든 문자열을 나타낸다. im, him, hhim, hhhim...

3. '+' 특수 문자 '+'는 바로 앞의 문자를 의미하며 그 문자가 하나 이상임을 나타낸다. '*'와 마찬가지로 앞에 한 문자가 있어야 하며 이 문자가 최소 하나 이상 존재하는 모든 문자열을 포함한다.

 

사용예 내  용 해당문자열
s+e 문자 e앞에 s가 최소한 하나 이상 존재하는 모든 문자열을 나타낸다. se, sse, ssse, sssse...

4. '?' 특수 문자 '?'는 바로 앞의 문자가 없거나 혹은 있음을 나타낸다. 예를 들면, s?e는 '?' 앞의 문자 s가 없거나 하나 존재하는 문자열 e나 se를 포함한다.
사용예 내  용 해당문자열
th?e t와 e사이에 h가 하나 있거나 혹은 없는 문자열과 일치한다. te, the, their, lotte...

5. '^' 특수 문자 '^'는 바로 뒤의 문자열을 기준으로 이것과 동일한 문자열로 시작되는 것을 가리킨다. 
사용예 내  용 해당문자열
^The The로 시작하는 모든 문자열을 나타낸다. The girl is beautiful! Theate.
^a?bc bc나 abc 로 시작하는 모든 문자열을 나타낸다. bc++3.0, abcdef
^.e e 앞에 한 글자가 존재하는 문자열로 시작하는 모든 문자열을 나타낸다 he, me, request,
^s.e? s와 임의의 한 문자로 시작하고 그 뒤에 문자 e가 하나 있거나 혹은 없는 문자열을 나타낸다. sa, sae, sb, sbe...

6. '$' 특수 문자 '$'는 문자열의 맨 마지막을 가리킨다.
사용예 내  용 해당문자열
a?bc$ bc로 끝나는 문자열 앞에 문자 a가 없거나 하나 존재하는 문자열과 일치한다. eeabc, seebc, bc...
t.e$ t와 임의의 한 글자, 그리고 그 다음에 e로 연결되어 끝나는 문자열과 일치한다. onthetoe, bctae, appetitte.
s?e+$ 첫 글자는 s나 e로 시작하고 하나 이상의 e로 끝나는 문자열과 일치한다. e, se, ee, eee, see...
^the$ the로 시작해서 the로 끝나는 문자열과 일치한다. 즉, 이 경우는 문자열 자체가 the 뿐인 경우에만 일치한다. the...

7. '[]' 특수 문자 각괄호 []는 []안에 있는 문자열 중엣 하나의 문자만을 의미한다. []안에서 범위를 지정할 때에는 '-' 문자를 사용한다. 즉, [a-d]는 [abcd]와 동일하며 [0-9]는 [0123456789]와 같은 의미이다.
사용예 내  용 해당문자열
[ab]cd acd 또는 bcd를 포함하는 문자열과 일치한다. acd, tacde, "bcd"...
^[ab]cd acd 또는 bcd로 시작하는 문자열과 일치한다. acds, bcdt...
[a-z] 영문 소문자 한 글자를 포함하는 문자열과 일치한다. a0c2ds, ta123cde..
[a-zA-Z] 영문 소문자나 대문자 한 글자를 포함하는 문자열과 일치한다. LINUX, 386AT..
[0-9] 십진수 한자를 포함하는 문자열과 일치한다. a0c2ds, ta123cde, 386..
ga[a-z] 하나의 영문 소문자 앞에 ga를 갖는 문자열과 일치한다. LINgazUX, gazzett..
^ab[cd]ef abcef 또는 abdef로 시작하는 문자열과 일치한다. abcef0z, abdef386..
  문자로 시작하는 모든 문자열과 일치한다.  
^[a-zA-Z] 영문소문자 한자 이상을 갖는 문자열과 일치한다. LINgazUX, abcef0z..
[a-z]+ ab,aB,Ab,AB를 포함하는 문자열과 일치한다. tgabcadcef, MySQL..
[aA][bB] ab,aB,Ab,AB를 포함하는 문자열과 일치한다. 386ABIT,
.[a-zA-Z0-9]$ 콤마와 하나의 영문자 또는 숫자로 끝나는 문자열과 일치한다. abdef38,6..

만일 원하지 않는 문자를 제외한 나머지 문자를 가리킬 때에는 []안의 첫 문자로 '^'를 사용한다.
사용예 내  용 해당문자열
[^ab]cd acd 와 bcd를 제외하고는 패턴 .cd와 같다. 즉, cd 앞에 a나 b를 제외한 하나의 문자를 포함하는 문자열과 일치한다. ccd, scd, 018cd..
s[^ab]t sat와 sbt를 제외하고는 패턴 s.t와 같다. 즉, t앞에 a나 b를 제외한 임의의 한문자와 그앞에 s가 있는 문자열과 일치한다. sct, sdt, settle..
[^a-z] 영문 소문자를 제외한 한글자를 포함한 문자열과 일치한다. MySQL, 199,2..
[^a-zA-Z] 영문자를 제외한 한글자를 포함하는 문자열과 일치한다. gazscd1, abcef0z..
[^0-9] 숫자를 제외한 한글자를 포함하는 문자열과 일치한다. settle, LINUX..

8. '{}' 특수 문자 중괄호 {}는 {}앞에 있는 문자나 문자열의 개수를 결정한다.
사용예 내  용 해당문자열
a{2}b aab를 가진 문자열과 일치한다. 즉, {2}는 {}앞에 있는 문자 a의 개수가 2개임을 의미한다 aab,
a{2,}b a의 개수가 최소한 2개 이상인 문자열을 포함하는 문자열과 일치한다. aab, aaab, aaaab...
a{1,3}b b앞에 1개부터 3개까지의 a를 갖는 문자열을 포함하는 문자열과 일치한다. ab, aab, aaab..

결국 앞에서 사용한 패턴 '*'는 중괄호로 표현하면{0,}과 같은 의미이고 '+'는 {1,}과 '?'는 {0,1}과 각각 같은 의미임을 알 수 있다.

9. '()' 특수 문자 둥근괄호 () 는 () 안에 있는 글자들을 그룹화 한다.
사용예 내  용 해당문자열
a(bc){2} a 뒤에 bc의 개수가 두 개인 문자열 abcbcf를 포함하는 모든 문자열과 일치한다. [bc]가 b 또는 c중 하나를 의미하는 것에 비해 (bc)는 bc를 하나의 그룹으로 처리한다. docabcbctor, tabcbc++..
a(bc)* a 뒤에 bc 가 없거나 하나 이상인 문자열과 일치한다. sea, abcd, abcbcbcbc..

10. '|' 특수 문자 '|'는 OR 연산자이다.
사용예 내  용 해당문자열
he|she he 나 she를 포함하는 문자열과 일치한다. he is hansome,
(he|she)is is 앞에 he 나 she를 포함하는 문자열, 즉 heis나 sheis를 포함하는 모든 문자열과 일치한다.  
(le|li)*ft ft 앞에 le 나 li 가 없고 하나 이상인 문자열과 일치한다. mlefto, lft, lelift,
mo(no)+ mo 뒤에 no가 하나 이상인 문자열과 일치한다. mono, monono..

문자 클래스(character class) 패턴을 [a-z]나 [A-Z],[0-9]로 표현하는 대신 다음과 같이 문자 클래스(character class)로 간단하게 표현할 수도 있다.
·[[:alpha:]] : 알파벳 문자 중 하나를 의미하며 [a-zA-Z], 또는 [a-Z]와 동일한 표현이다.
·[[:digit:]] :숫자 한 자를 의미하며 [0-9]와 동일한 표현이다.
·[[:alnum:]] : 알파벳 문자나 숫자 중 하나를 의미하며 [a-zA-Z0-9]와 동일한 표현이다.
·[[:space:]] : 공백 문자()를 의미한다.

정규 표현식에서 특수 문자의 표현 지금까지 정규 표현식에서 사용한 여러 특수 문자를 특수 문자가 아닌 그 문자 자체의 의미로 사용하려면 특수 문자 앞에 역슬래시('\')문자를 붙여 escape 시켜야 한다. 정규 표현식에서 escape 시켜야 하는 특수 문자로는 다음과 같은 것들이 있다. 
^ . [ ] $ ( ) | * + ? { } \
·\*+ : 문자 '*'이 하나 이상 포함된 모든 문자열과 일치한다. 이것은 정규 표현식에서 사용하는 특수 문자 '*'를 '\*'와 같이 escape 시킴으로써 문자열에서 '*'가 포함된 문자열을 찾는다.
예) *notice***, dictsh*eionary

·\[RE:[1-9][0-9]*\] : "["와 "RE:", 그리고 0을 제외한 하나의 숫자와 0또는 하나 이상의 0을 포함 한 숫자, 그리고 "]"를 순서대로 포함하는 모든 문자열과 일치한다. 즉, 이는 게시판에 답장 글을 올릴 때의 "[RE:12]"와 같은 패턴을 의미한다.
예) [RE:9], [RE:21]*eionary

·[*\/+?{}.] : "*"나 "\", "/", "+", "?", "{", "}", "."중 하나를 포함하는 모든 문자열과 일치한다. 특수문자[]안에서는 위의 경우와 달리 예외가 적용된다. 즉, []안에서는 특수 문자를 문자 자체로 표현하기 위해 해당 문자를 별도로 escape 시키지 않아도 된다.
예) [RE:21]*eionary, turboc++, ce{le}brity, hello?, ac/monoe
7.2. PHP에서 정규 표현식 관련 함수
PHP에서 정규 표현식을 이용하는 함수는 다음과 같은 것들이 있다.

ereg 함수 ereg() 함수의 정의는 다음과 같다. 
int ereg(string pattern, string string, array [regs]);
  검색 대상 문자열(string)에서 정규 표현식으로 나타낸 패턴(pattern)과 일치하는 문자열이 발견될 경우에 true를, 발견되지 않을 경우에는 false를 반환한다.
ereg() 함수는 검색 대상 문자열에서 지정한 패턴이 존재하는지를 검사할 때 사용한다. 함수의 첫 번째 인자로 패턴 문자열을, 두 번째 인자로 검색할 문자열을 주면 이 문자열을 검색하여 지정한 패턴이 문자열 내에 존재하는지를 그 결과로 반환한다.
다음의 예제를 보자. 
<?

$string = "[RE:8] 게시판 포스팅 테스트";

$res = ereg("\[RE:[1-9][0-9]*\]", $string);

if($res) {
  echo("pattern for \"$string\" : found!<p>");
} else {
  echo("pattern for \"$string\" : not found!<p>");
}

$string = array("yunka0803", "informediary", "92kdkang", "JaeDoNam");

while(list($key,$val) = each($string)) {
  if(ereg("^[[:alpha:]][[:alnum:]]{7,9}$",$val)) {
     echo("pattern for \"$val\" : found!<br>");
  } else {
     echo("pattern for \"$val\" : not found!<br>");
  }
}

?>
[예제3.1] ereg() 함수는 패턴과 일치하는 문자열을 찾는다.

3행에서 11행은 문자열 "[RE:8] 게시판 포스팅 테스트"를 검색하여 지정한 패턴
"\[RE:[1-9][0-9]*\]"과 일치하는 문자열이 존재하는지를 조사한다. 5행에서 지정한 패턴 문자열 "\[RE:[1-9][0-9]*\]"은 "[RE:" 와 "]" 사이에 한 자리나 두 자리 이상의 숫자를 포함하는 모든 문자열과 일치한다. 예를 들면, "RE:10]" 이나 "RE:9]" 와 같은 문자열이 지정한 패턴에 일치하는 경우이다. 그러나 [RE:02]와 같은 문자열은 패턴에서 첫 자리 숫자를 1에 9까지의 숫자로 제한하였으므로 패턴과 일치하지 않는다.

위 예제에서 3행의 문자열 "[RE:8] 게시판 포스팅 테스트"는 패턴과 일치하는 문자열 "[RE:8]"을 포함하고 있으므로 5행의 ereg("\[RE:[1-9][0-9]*\]", $string) 함수의 실행결과로 $res는 true 값을 갖게 된다. 따라서 8행이 실행된다.
13행에서 21행은 배열 변수 $string의 모든 원소에 대해 지정한 패턴을 검색하여 일치하는 문자열이 존재하는지를 그 결과로 출력하는 예제이다.

위 예제에서 지정한 패턴 문자열 "^[[:alpha:]][[:alnum:]]{7,9}$"는 첫 자리로 알파벳 문자와 그 뒤에 최소 7개에서 최대 9개까지의 알파벳이나 숫자로 된 문자열을 나타낸다. 결과적으로는 첫 자는 반드시 문자로 시작하는 최소 8개에서 최대 10개까지의 문자 또는 숫자를 포함한 문자열이어야 한다. 또 패턴의 앞뒤에 각각 '^' 과 '$' 이 있으므로 이들 문자열이 다른 문자열 속에 포함되어 있지 않고 단독으로 존재할 경우에만 지정된 패턴과 일치하게 된다.
[예제3.1]의 실행 결과는 다음과 같다. 
pattern for "[RE:8] 게시판 포스팅 테스트" : found!

pattern for "yunka003" : found!
pattern for "informediary" : not found!
pattern for "92kdkang" : not found!
pattern for "JaeDoNam : found!
변수 $string의 첫 번째 원소인 "yunka0803"은 총 9개의 문자로 첫 자가 y로 시작하므로 지정한 패턴과 일치한다. 그러나 두 번째 원소인 "informediary"는 총 12자로 10자를 초과하므로 패턴과 일치하지 않는다. 세 번째 원소인 "92kdkang"는 첫 자가 알파벳이 아닌 숫자로 시작하므로 일치하지 않으며, 네 번째 원소인 "JaeDoNam"는 총 8자의 문자열이므로 패턴과 일치하게 된다.

한편 ereg() 함수의 정의를 보면 패턴 문자열과 검색 대상 문자열외에 세 번째 인자로 배열 변수를 갖는데 이 세 번째 인자를 주고서 함수를 호출하게 되면 함수 실행 후 필요한 값을 이 배열 변수로부터 얻어낼 수도 있다. 즉, 세 번째 인자를 포함해서 ereg() 함수를 호출하면 패턴 문자열 중 괄호로 둘러싸인 부분의 패턴과 일치하는 문자열이 검색 대상 문자열에서 발견될 경우 그 발견된 문자열이 세 번째 인자로 주어진 배열 변수에 저장이 된다. 쉽게 이해가 가지 않는다면 다음 예제의 결과를 통해 이 세 번째 인자가 갖는 값의 의미를 파악해보자. 

<?

$string = "2000-1-28";

If(ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $string, $regs)) {
   echo("$regs[2]월 $regs[3]일 $regs[1]년<p>");
   for($i = 0; $i < sizeof($regs); $i++) {
      echo("\$regs[$i] : $regs[$i]<br>");
   }
   echo("<p>");
} else {
   echo("날짜형식이 잘못되었습니다 : $string<p>");
}

$string = "MidTerm - 9247167:87:B+";

$pattern = "([0-9]{7}):([0-9]{1,3}):([A-D|F][+]?)";

if(ereg($pattern,$string,$regs)) {
  echo("\$regs[0] : $regs[0]<br>");
  echo("\$regs[1] : $regs[1]<br>");
  echo("\$regs[2] : $regs[2]<br>");
  echo("\$regs[3] : $regs[3]<p>");
  echo("학번이 $regs[1]인 학생의 점수는 $regs[2]점으로 최종학점은 $regs[3]입니다.<p>");
} else {
  echo("pattern for \"$string\" not found!<br>");
}

?>

[예제3.2] ereg() 함수의 세 번째 인자의 사용
위의 실행 결과는 다음과 같다. 
1월 28일 2000년
$regs[0] : 2000-1-28
$regs[1] : 2000
$regs[2] : 1
$regs[3] : 28
$regs[4] :
$regs[5] :
$regs[6] :
$regs[7] :
$regs[8] :
$regs[9] :

$regs[0] : 9247167:87:B+
$regs[1] : 9247167
$regs[2] : 87
$regs[3] : B+

학번이 9247167인 학생의 점수는 87점으로 최종학점은 B+입니다.
[예제3.2]의 3행에서 13행까지의 코드는 사용자가 입력한 날짜 정보(여기서는 3행의 "2000-1-28")를 검색하여 정해진 패턴과 일치하면 세 번째 인자로 설정한 배열 변수(여기서는 5행의 $reg변수)의 값을 이용하여 날짜 정보를 출력하는 예제이다.
5행에서 ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $string $regs)와 같이 세 번째 인자인 $regs와 함께 ereg() 함수를 호출하면 이 함수는 사용자가 입력한 날짜 정보 $string에서 패턴 "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})"와 일치하는 문자열을 찾되 이 때 패턴 문자열 중 괄호로 둘러싸인 부분과 일치하는 문자열이 발견될 경우 해당 문자열을 배열 변수 $regs에 저장하게 된다.

즉, 패턴 문자열을 보면 모두 세 개의 괄호로 둘러싸인 부분이 있음을 볼 수 있다. 첫 번째는 네 자리 숫자를 의미하는 "([0-9]{4})"로 이 패턴에 일치하는 문자열은 "2000-1-28" 중 "2000" 이다. 따라서 배열 변수 $regs[1]에는 이 "2000"이 저장된다.
다음으로 두 번째 괄호로 둘러싸인 부분은 두 개의 숫자를 의미하는 "([0-9]{1,2})"로 '-'문자 다음에 있어야 하므로 "2000-1-28"중 "1"에 해당한다. 따라서 $regs[2]에는 "1"이 저장된다.

마찬가지로 세 번째 괄호로 둘러싸인 부분 역시 두 번째 패턴과 동일하므로 $regs[3]에는 "28"이란 값이 저장된다. 말하자면 "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})"는 "(2000)-(1)-(2)"에 해당하고 패턴과 일치하는 순서에 따라 배열 변수 $regs[1], $regs[2], $regs[3]에 각각 패턴과 일치하는 순서에 따라 배열 변수 $regs[1], $regs[2], $regs[3]에 각각 패턴과 일치되는 값 "2000", "1", "28"이 저장되는 것이다. 그리고 $regs[0]에는 지정한 패턴과 일치하는 문자열이 저장된다.
7행에서 9행은 배열 변수 $regs의 내용을 출력하는 코드인데 실행 결과를 보면 배열 변수의 크기가 10으로 잡혀있다. 즉, 배열 변수 $regs에 담을 수 있는 문자열은 최대 9개까지임을 알 수 있다.

예제를 더 보자. 15행에서 27행까지의 코드는 "9247167:87:B+" 와 같이 ':'로 학생의 학번과 성적, 학점정보를 적은 문자열을 지정한 패턴에 따라 검색하여 그 결과를 $regs 배열 변수의 값으로 출력하는 예제이다.

검색 대상 문자열에서 학번과 성적, 학점 등 각각의 정보를 추출하기 위하여 패턴을
"([0-9]{7}):([0-9]{1,3}):([A-F][+]?)"와 같이 정의하였다. 첫 번째 괄호 안의 패턴 "([0-9]{7})"은 7자리 숫자로 구성되는 학번과 일치하며 두 번째 괄호 안의 패턴 "([0-9]{1,3})"은 0점에 100점까지의 성적과 일치한다. 또한 세 번째 괄호 안의 패턴 "([A-F][+]?)"은 학점과 일치한다. 따라서 15행의 "MidTerm - 9247167:87:B+" 문자열을 대상 문자열로 함수를 호출하면 $regs[1]에는 학번 "9247167"이 $regs[2]에는 점수 "87"이 $regs[3]에는 학점 "B+"가 저장된다. 따라서 24행과 같이 $regs 배열 변수의 값을 이용하여 관련 정보를 출력할 수 있다.

eregi 함수 eregi() 함수의 정의는 다음과 같다. 
int eregi(string pattern, string string, array [regs]):
  검색 대상 문자열(string)에서 정규 표현식으로 나타낸 패턴(pattern)과 일치하는 문자열이 발견될 경우에 true를, 발견되지 않을 경우에는 false를 반환한다. 단, 이때 대소 문자는 구분하지 않는다.
eregi() 함수는 앞의 ereg() 함수와 동일한 기능을 수행한다. 두 함수의 유일한 차이점은 ereg() 함수는 대소 문자를 구분하는 반면 eregi() 함수는 대소 문자를 구분하지 않는다는 점이다. 

<?

$string = "TeaST 99";

$pattern = "^[A-Z]{5}";

if(ereg($pattern,$string)) {
  echo("pattern for \"$string\" : found!<br>");
} else {
   echo("pattern for \"$string\" : not found!<br>");
}

if(eregi($pattern,$string)) {
  echo("pattern for \"$string\" : found!<br>");
} else {
  echo("pattern for \"$string\" : not found!<br>");
}

?>

[예제3.3] ereg() 함수와 eregi() 함수의 차이

실행결과는 다음과 같다. 
pattern for "TeaST 99" : not found!
pattern for "TeaST 99" : found!
7행에서 ereg() 함수의 호출 결과 대상 문자열 "TeaST 99"에는 다섯 자리의 연속된 영문 대문자가 없으므로 false를 반환한다. 따라서 10행이 실행된다.
그러나 13행의 eregi() 함수는 대소 문자를 구별하지 않으므로 "TeaST 99" 문자열이 영문자 다섯 개를 지정한 패턴과 일치한다고 판단하여 true를 반환한다. 따라서 14행이 실행된다. 이와 같이 두 함수의 차이는 대소 문자의 구분 여부에 있으며 다음에서 다룰 ereg_replace() 함수와 eregi_replace() 함수의 차이 역시 대소 문자의 구분 여부에 있다.

ereg_replace 함수 ereg_replace() 함수의 정의는 다음과 같다. 
string ereg_replace(string pattern, string replacement, string string);
 
검색 대상 문자열(string)에서 정규 표현식으로 나타낸 패턴(pattern)과 일치하는 문자열을 찾아 지정한 문자열(replacement)로 바꾼다. ereg_replace() 함수는 문자열에서 지정한 패턴과 일치하는 문자열을 찾아 다른 문자열로 바꿀 때 사용한다. 

<?

$string = "By viewing these pages";

$res = ereg_replace("these", "those", $string);
echo("$res");             // "By viewing those pages"

?>

[예제3.4] ereg_replace() 함수는 패턴과 일치하는 문자열을 찾아 원하는 문자열로 대체한다.

5행의 eteg_replace("these", "those", $string) 함수는 문자열 변수 "By viewing these pages"에서 "these"라는 문자를 찾아 이 문자열을 "those"로 바꾼다. 따라서 실행 결과 원래의 문자열 "By viewing these pages"는 "By viewing those pages"로 바뀌어 출력된다.

이번에는 첫 번째 인자로 "these"와 같은 특정 문자열이 아닌 패턴을 지정하여 이 패턴과 일치하는 문자열을 찾아 바꾸어보자. 

<?

$string = "By viewing these pages";

$res = ereg_replace("(t[[:alpha:]]+)","that",$string);
echo("$res<br>");                 // "By viewing that pages"

$res = ereg_replace("(t[[:alpha:]]+)","\\1",$string);
echo("$res<br>");                 // "By viewing these pages"

$res = ereg_replace("t([[:alpha:]]+)","\\1",$string);
echo("$res<br>");                 // "By viewing hese pages"

$res = ereg_replace("t([[:alpha:]]+)","that\\1",$string);
echo("$res<br>");                 // "By viewing thathese pages"

$res = ereg_replace("t([[:alpha:]]+) ([a-z]+s$)","\\1",$string);
echo("$res<br>");                 // "By viewing hese"

$res = ereg_replace("t([[:alpha:]]+) ([a-z]+s$)","\\2",$string);
echo("$res<p>");                  // "By viewing pages"

?>

[예제3.5] ereg_replace() 함수에서의 \digit의 의미

먼저 5행의 패턴 "(t[[:alpha:]]+)"을 보자. 이 패턴은 "t"로 시작하고 하나이상의 알파벳 문자가 연결된 문자열, 즉 t로 시작하는 하나의 단어와 일치하는 패턴이다. 검색 대상 문자열 "By viewing these pages"에서 이 패턴과 일치하는 문자열은 "these"이다. 따라서 5행의 함수 호출 부분은 바꾸어 표현하면 ereg_replace("these","that",$string)와 같으므로 "these"를 "that"으로 바꾼 문자열 "By viewing that pages"가 함수 실행의 결과로 출력된다.
8행을 보면 ereg_replace("(t[[:alpha:]]+)", "\\1", $string)처럼 바꿀 문자열위치에 "\\1"와 같은 문자열이 있는 것을 볼 수 있다. 앞의 ereg() 함수에서 마지막 세 번째 인자를 주어 호출했을 때 함수에서 지정한 패턴 문자열 중 괄호 안의 패턴과 일치하는 문자열이 존재할 경우 이 문자열이 세 번째 인자인 배열 변수에 저장된다는 것을 기억할 것이다.
ereg_replace() 함수에서의 "\숫자" 역시 바로 그와 비슷한 개념이다. 즉, 지정한 패턴 문자열중 괄호 안의 패턴과 일치하는 문자열이 검색 대상 문자열 내에 존재할 때 이 문자열을 그 값으로 갖는 변수라고 볼 수 있다.
8행에서 괄호 안의 패턴 "(t[[:alpha:]]+)"에 일치하는 문자열은 대상 문자열 "By viewing these pages"에서 찾아보면 "these"이다. 따라서 이 "these"라는 문자열은 "\1"로 표현된다. 여기서 "1"은 첫 번째 괄호 안의 패턴과 일치되는 문자열임을 가리킨다. 결국 8행의 함수 호출 부분 ereg_replace("(t[[:alpha:]]+)", "\\1", $string)을 바꾸어 표현하면 ereg_replace("(t[[:alpha:]]+)", "these", $string)와 같다. 따라서 8행의 해석결과 바뀔 문자열과 바꿀 문자열이 모두 "these"이므로 결과적으로 출력 결과는 원래의 문자열과 같아진다.

11행의 패턴은 5행과 달리 "t"가 괄호 앞에 나와 있는 "t([[:alpha:]]+)"이다. 결과적으로 이 패턴에 일치하는 문자열은 역시 "these"이다. 그러나 "\1"에 저장되는 문자열은 달라진다. 패턴 "t([[:alpha:]]+)"와 일치하는 문자열은 "these"이지만 전체 패턴 문자열 중 괄호 안의 패턴 "[[:alphp:]]+)"와 일치하는 문자열은 "these"가 아닌 "hese"이기 때문이다. 따라서 "\1"에는 "hese"가 저장된다. 결국 11행의 함수 호출 부분 ereg_replace("t([[:alphp:]]+)", \\1", $string)을 바꾸어 표현하면ereg_replace("t([[:alpha:
]]+)", "hese", $string)와 같으므로 "these"를 "hese"로 바꾼 문자열 "By viewing hese pages"이 함수 실행의 결과로 출력된다.

14행은 11행과 동일하다. 단지 채체할 문자열로 "that\\1"를 주었는데 이는 바꾸어 표현하면 "thathese"와 같으므로 실행 결과 문자열 "By viewing thathese pages"이 출력된다. 17행의 함수 호출에서는 패턴 문자열 내에 괄호가 두 개 존재한다. 각각의 괄호 내 패턴에 일치하는 문자열은 "hese"와 "s"로 끝나는 문자열"pages"이다. 즉, 첫 번째 괄호 내 패턴과 일치하는 문자열 "hese"는 "\1"에 저장되고, 두 번째 괄호 내 패턴과 일치하는 문자열 "pages"는 "\2"에 저장된다. 결국 17행의 함수 호출 부분은 바꾸어 표현하면 ereg_replace("t([[:alpha:]]+)([a-z]+s$)", "hese", $string)와 같으므로 "these pages"를 "hese"로 바꾼 문자열 "By viewing hese"가 함수 실행의 결과로 출력된다.

20행은 17행과 동일하며 바꿀 문자열로 "\1" 대신 "\2"를 지정하였다. 따라서 함수 호출 부분은 바꾸어 표현하면 ereg_replace("t([[:alpha:]]+)([a-z]+s$)", "pages", $string)가 되므로 "these pages"를 "pages"로 바꾼 문자열 "By viewing pages"가 함수 실행의 결과로 출력된다.
괄호 내 패턴과 일치하는 문자열은 이처럼 "\1", "\2", "\3"... 등과 같이 변수처럼 저장이 되며 총 "\9"까지 사용 가능하다.

eregi_replace 함수 eregi_replace() 함수의 정의는 다음과 같다. 
string eregi_replace(string pattern, string replacement, string string);
  검색 대상 문자열(string)에서 정규 표현식으로 나타낸 패턴(pattern)과 일치하는 문자열을 찾아 지정한 문자열(replacment)로 바꾼다. 단, 이때 대소 문자는 구분하지 않는다.

split 함수 split() 함수의 정의는 다음과 같다. 
array split(string pattern, string string, int[limit]);
  정규 표현식으로 나타낸 패턴(pattern)과 일치하는 문자열을 경계로 검색 대상 문자열(string)을 나누어 배열에 저장한다.
split() 함수는 문자열 처리 함수 부분에서 잠시 소개한 적이 있다. 여기서는 정규 표현식을 이용하여 split() 함수를 실행하여 보자. 
<?

$string = "이완철    김영미               길현수 강현민";

$arr = split("[[:space:]]+",$string);

for($i = 0; $i < sizeof($arr); $i++) {
  echo("\$arr[$i] : $arr[$i]<br>");
}

?>
[예제3.6] split() 함수의 사용

누군가로부터 회원 명을 받았다고 가정하다. 그런데 사람 이름이 정해진 간격에 따라 균등하게 정렬되어 있지 않고 3행의 변수 $string처럼 하나 이상 임의 개수의 공백 문자를 두고 떨어져 있다면 어떻게 이들 회원 이름만을 구분하여 뽑아낼 것인가?
이름과 이름 사이의 간격이 똑같지 않다면 문자열 처리를 위한 explode() 함수만으로는 불가능하다. 이때 바로 정규 표현식을 이용하여 split() 함수를 실행하면 쉽게 해결할 수 있다.
explode() 함수가 정해진 특정 문자나 문자열을 경계로 대상 문자열을 나누어 배열에 저장하는 반면에 split() 함수는 특정 문자나 문자열 대신 정규 표현식을 인자로 전달함으로써 보다 다양한 패턴에 따라 문자열을 나눌 수 있다.

5행의 split("[[:space:]]+",$string)에서 첫 번째 인자로 준 패턴은 하나 이상의 공백 문자를 가리키며 따라서 이를 경계로 하여 전체 문자열 $string을 나눈다. 따라서 이름과 이름 사이의 공백이 몇 개든 상관없이 배열 $arr에는 공백 문자를 경계로 나누어진 네 명의 이름이 순서대로 저장된다.

[예제3.6]의 실행 결과는 다음과 같다. 
$arr[0] : 이완철
$arr[1] : 김영미
$arr[2] : 길현수
$arr[3] : 강현민
7.3. 정규 표현식을 이용한 예제
게시판 입력 항목 확인하기 정규 표현식을 이용하여 사용자가 게시판이나 BBS에 글을 올릴 때 이름과 제목, 본문 내용을 제대로 입력했는지를 체크할 수 있는 코드를 작성해보자.
여기서는 사용자가 입력 양식에 이름과 제목, 본문 내용을 입력하고 전송 버튼을 눌렀을 때 해당 PHP3 스크립트 파일에서 이들이 전송되어지는 각 항목의 문자열을 검사하여 사용자가 입력을 하지 않았거나 공백 문자열만을 입력하였을 경우를 체크하도록 하였다. 
<html>
<body>

<form method="POST" action="isnull.php3">

<table width="602" border="0" cellspacing="0" cellpadding="1" align="center">
<tr>
  <td bgColor="#8080FF">

  <table width="600" border="0" cellspacing="1" cellpadding="5" align="center">
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>이 름</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="text" name="name" size="20" maxlength="10"></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>제 목</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="text" name="subject" size="30" maxlength="40"></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>비 밀 번 호</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="password" name="passwd" size="10"> <font size="2">(영문과 숫자를 조합한      6-8자)</font></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>메 시 지 본 문</font></td>
     <td width="500" bgColor="#FAFAEE"><textarea name="comment" cols="50" rows="10"></textarea>
  </tr>
  <tr>
     <td align="center" colspan="2" bgColor="#CFD0ED">
     <font size=2>
     <input type="submit" value="글 쓰 기">
     <input type="reset" value="취   소">
     </font>
     </td>
  </tr>
  </table>

  </td>
</tr>
</table>

</form>

</body>
</html>
[예제3.7] 게시판 입력 폼을 위한 HTML 코드

[예제3.7]에서는 이름과 제목, 비밀번호와 메시지 본문의 네 가지 항목을 입력받는다. 10행에서 35행까지는 사용자 입력 양식을 위한 테이블 코드로 여기에 사용자가 입력한 네 가지 항목에 대한 문자열은 사용자가 입력을 마치고 전송 버튼을 눌렀을 때 4행에서 지정한 isnull.php3 파일로 전송된다.
전송되는 문자열은 [예제3.7]의 입력 양식에서 지정한 이름과 동일한 이름을 갖는 변수로 전달된다. 즉, 이름은 $name으로, 제목은 $subject로, 비밀번호는 $passwd로 그리고 메시지 본문은 $comment 라는 변수로 각각 전달된다. 그러면 isnull.php3 파일이 이들 변수를 넘겨받으면서 실행이 되므로 이 실행 코드에 각 변수에 대한 문자열 체크를 하여 사용자가 입력하지 않았거나 공백 문자열만을 입력하였는지를 확인하는 코드를 앞 부분에 추가하면 된다.

다음의 코드는 정규 표현식을 이용하여 문자열을 체크하기 위한 isnull.php3 스크립트 파일의 내용이다. 
<?

if(ereg("([^[:space:]]+)", $name)) {
  echo("입력하신 이름은 \"${name}\"입니다.<p>");
} else {
  echo("이름란에 입력하신 문자열이 공백문자열이거나 이름을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("([^[:space:]]+)", $subject)) {
  echo("입력하신 제목은 \"${subject}\"입니다.<p>");
} else {
  echo("제목란에 입력하신 문자열이 공백문자열이거나 제목을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("(^[0-9a-zA-Z]{6,8}$)", $passwd, $regs)) {
  echo("입력하신 암호는 \"$regs[1]\"입니다.<p>");
} else {
  echo("암호는 최소 6자에서 최대 8자까지의 영문자 또는 숫자여야 합니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("([^[:space:]]+)", $comment)) {
  echo("입력하신 본문의 내용은 \"${comment}\"입니다.<p>");
} else {
  echo("본문란에 입력하신 문자열이 공백문자열이거나 본문을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

?>
[예제3.8] isnull.php3 스크립트

3행에서 8행까지는 앞의 입력 양식 중 이름 즉, 변수 $name의 문자열을 정규 표현식을 이용하여 검사하는 코드이다. 4행엣 ereg("([^:space:]]+)", $name) 함수는 변수 $name이 가진 문자열에서 패턴 "([^:space:]]+)"과 일치하는 문자열이 존재하는 지를 검사한다. 패턴 "([^:space:]]+)"는 공백 문자를 가리키는 문자 클래스(character class) "[:space:]"를 사용하여 공백 문자가 아닌 그 외의 문자를 하나 이상 포함하는 모든 문자열과 일치한다.
따라서 3행의 함수 ereg("([^:space:]]+)", $name)는 사용자가 입력 항목의 이름란에 아무 것도 입력하지 않았거나 스페이스 키만을 눌러 하나 이상의 공백 문자열만을 입력했을 경우를 제외하고는 true를 반환하므로 4행에서 입력 값으로 타당한 값을 출력한다. 만일 사용자가 이름을 입력하지 않았거나 공백 문자열만을 입력하면 3행의 함수는 false를 반환하므로 6행에서 오류 메시지를 출력한다.
10행에서 15행은 제목을 가리키는 변수 $subject에 대한 문자열 검사를 수행하는 코드로 그 내용은 $name에 대한 코드와 같다.
17행에서 22행은 비밀번호인 $passwd에 대한 문자열을 검사하는 코드이다. 비밀번호는 알파벳과 숫자를 조합할 수 있으며 최소 6자에서 최대 8자까지여야 한다. 따라서 이러한 조건에 맞는 비밀번호 문자열을 검출하려면 패턴은 다음과 같아야 한다. 
^[0-9a-zA-z]{6,8}$
위의 패턴은 숫자와 영문 대소문자 즉, 알파벳 문자와의 조합으로 된 문자열 중 최소 6자리 이상 8자리 이하의 모든 문자열과 일치한다. 따라서 17행의 ereg("(^[0-9a-zA-Z]{6,8}$)", $passwd, $regs) 함수는 사용자가 입력한 비밀번호 $passwd가 패턴과 일치하는지를 검사하여 그 결과를 출력한다.
여기서 함수 호출시 세 번째 인자로 $regs를 준 것을 볼 수 있다. 앞의 ereg() 함수에서 본 것처럼 $regs 변수는 패턴 문자열중 괄호로 둘러싸인 부분과 일치하는 문자열을 그 원소로 갖는 배열 변수이므로 17행의 패턴 "(^[0-9a-zA-Z]{6,8}$)" 과 일치하는 문자열, 즉 타당한 비밀번호를 입력하였을 경우 그 값을 저장하는 변수이다. 따라서 18행에서와 같이 $passwd 대신 $regs[1]로 표현하여 출력할 수도 있다.

17행의 ereg() 함수는 대소 문자를 구분하지 않는 eregi() 함수를 이용하여 [a-zA-Z] 대신 [a-z]와 같이 줄여서 표현할 수도 있다. 즉, 다음의 두 코드는 동일한 표현이다. 
if(ereg("(^[0-9a-zA-Z]{6,8}$)", $passwd, $regs))        // ereg() 함수호출
if(eregi("(^[0-9a-z]{6,8}$)", $passwd, $regs)           // eregi() 함수호출
또한 표현식 [0-9a-zA-Z]는 알파벳과 숫자의 조합이므로 이를 가리키는 문자 클래스 [:alnum:]으로 줄여서 표현할 수도 있다. 
if(ereg("([[:alnum:]] {6,8}$)", passwd, $regs))           // 문자 클래스
24행에서 29행은 메시지 본문에 대한 문자열을 검사하는 코드로 $name이나 $subject의 경우와 동일하다.

전자우편 주소의 타당성 체크하기 3.2절의 정규 표현식 함수를 사용하여 사용자가 입력한 전자우편 주소가 유효한지를 검사할 수 있다.
사용자가 입력한 전자우편 주소의 타당성을 검증하기 위해서는 유효한 전자우편 주소에 대한 패턴을 정의하고 사용자가 입력한 전자우편 주소가 이 패턴에 일치하는지를 정규 표현식 함수로 검사해야 한다.

이를 위해 유효한 전자우편 주소에 대한 패턴을 만들어보자.
일반적으로 전자우편 주소는 세 부분으로 나누어진다. 예를 들면, jcafe@safelab.skku.ac.kr과 같이 앞의 계정(jcafe)과 뒤의 서버 이름 safelab.skku.ac.kr 그리고 그 사이에 있는 '@' 기호이다.
앞의 사용자 계정은 영문 소문자나 대문자, 숫자, 기호로는 음수 기호 '-'와 밑줄 기호 '_' 그리고 점('.')과 같은 문자의 조합으로 구성된다. 따라서 사용자 계정에 대한 패턴을 정의하면 다음과 같다. 
[_\.0-9a-zA-Z-]
뒤의 '-'는 범위를 나타내는 0-9이나 a-z, A-Z의 '-'와 혼동될 우려가 있으므로 보통은 []의 맨 앞이나 맨 뒤에 쓴다.
그러나 사용자 계정은 .jcafe@safelab.skku.ac.kr이나 khjung.@kornux.co.kr처럼 점('.')으로 시작하거나 점으로 끝날 수 없다. 따라서 첫 문자는 점이 아닌 다른 글자여야 하므로 위의 패턴은 다음과 같이 수정  해야 한다. 
[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*
뒤의 서버 이름 부분도 사용자 계정과 동일한 규칙을 갖는다. 다만 사용자 계정과 다른 점은 밑줄 기호 '_'는 서버 이름에 쓸 수 없다는 점이다. 따라서 서버 이름에 대한 패턴은 사용자 계정에서 밑줄 기호 '_'를 제외한 다음과 같다. 
[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*
사용자 계정과 서버 이름 사이에는 '@'가 있어야 하므로 결과적으로 유효한 전자우편 주소는 다음과 같은 패턴을 갖게 된다. 
^[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*@[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$
이제 이 패턴을 가지고 ereg() 함수를 호출하면 사용자가 입력한 전자우편 주소가 타당한 주소인지를 검사할 수 있다. 
if(ereg("(^[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*@[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$)", $email, $regs)) {
  echo("입력하신 전자우편주소는 \"$regs[1]\"입니다.<p>");
} else {
  echo("전자우편란에 입력하신 문자열이 공백문자열이거나 전자우편주소를 입력하지 않으셨습니다. 다시입력하여주십시요!<p>");
  exit;
}
[예제3.8] 전자우편 주소의 타당성 검사

1행에서 ereg() 함수는 사용자가 입력한 전자우편 주소($email)가 앞에서 정의한 패턴에 일치하는지를 검사한다. 만일 일치하면 2행에서 전자우편 주소를 출력하고 그렇지 않으면 4행에서 오류 메시지를 출력한다.
1행에서 함수 호출시 $regs 인자를 주었으므로 $regs[1] 변수에는 패턴 문자열 내 첫 번째 괄호 내의 패턴 즉, "^[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*@[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$"와 일치하는 문자열이 저장된다. 결국은 유효하다고 판정된 전자우편 주소가 저장된다.
이제 [예제3.7]의 게시판 입력 항목에 전자우편 주소를 추가한 코드를 보면 다음과 같다.
<html>
<body>

<form method="POST" action="validate_email.php3">

<table width="602" border="0" cellspacing="0" cellpadding="1" align="center">
<tr>
  <td bgColor="#8080FF">

  <table width="600" border="0" cellspacing="1" cellpadding="5" align="center">
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>이 름</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="text" name="name" size="20" maxlength="10"></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>제 목</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="text" name="subject" size="30" maxlength="40"></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>전 자 우 편</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="text" name="email" size="30" maxlength="40"></td>
  </tr>  
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>비 밀 번 호</font></td>
     <td width="500" bgColor="#FAFAEE"><input type="password" name="passwd" size="10"> <font size="2">(영문과 숫자를 조합한 6-8자)</font></td>
  </tr>
  <tr>
     <td width="100" align="left" bgColor="#CFD0ED"><font size=2>메 시 지 본 문</font></td>
     <td width="500" bgColor="#FAFAEE"><textarea name="comment" cols="50" rows="10"></textarea>
  </tr>
  <tr>
     <td align="center" colspan="2" bgColor="#CFD0ED">
     <font size=2>
     <input type="submit" value="글 쓰 기">
     <input type="reset" value="취   소">
     </font>
     </td>
  </tr>
  </table>

  </td>
</tr>
</table>

</form>

</body>
</html>
[예제3.9] 전자우편 주소를 추가한 게시판 입력 폼의 HTML 코드

사용자가 각 입력 항목에 값을 입력하고 전송하면 [예제3.9]의 4행에서처럼 validate_email.php3 스크립트 파일이 실행된다. validate_email.php3 파일의 내용은 다음과 같다. 

<?

if(ereg("([^[:space:]]+)", $name)) {
  echo("입력하신 이름은 \"${name}\"입니다.<p>");
} else {
  echo("이름란에 입력하신 문자열이 공백문자열이거나 이름을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("([^[:space:]]+)", $subject)) {
  echo("입력하신 제목은 \"${subject}\"입니다.<p>");
} else {
  echo("제목란에 입력하신 문자열이 공백문자열이거나 제목을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("(^[_0-9a-zA-Z-]+(\.[_0-9a-zA-Z-]+)*@[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$)", $email, $regs)) {
  echo("입력하신 전자우편주소는 \"$regs[1]\"입니다.<p>");
} else {
  echo("전자우편란에 입력하신 문자열이 공백문자열이거나 전자우편주소를 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("(^[0-9a-zA-Z]{6,8}$)", $passwd, $regs)) {
  echo("입력하신 암호는 $regs[1]입니다.<p>");
} else {
  echo("암호는 최소 6자에서 최대 8자까지의 영문자 또는 숫자여야 합니다. 다시입력하여 주십시오!<p>");
  exit;
}

if(ereg("([^[:space:]]+)", $comment)) {
  echo("입력하신 본문의 내용은 \"${comment}\"입니다.<p>");
} else {
  echo("본문란에 입력하신 문자열이 공백문자열이거나 본문을 입력하지 않으셨습니다. 다시입력하여 주십시오!<p>");
  exit;
}

?>

[예제3.10] validate_email.php3 스크립트

17행에서 22행까지가 전자우편 주소를 검사하기 위해 추가된 코드이다.
17행의 패턴 문자열을 보면 괄호가 세 개 있음을 알 수 있다. 즉, 첫 번째 괄호는 ("^[_0-9a-zA-Z-
]+(\.[0-9a-zA-Z-]+)*@[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$")이고 두 번째 괄호는 첫 번째 괄호 안에 있는 "(\.[0-9a-zA-Z-]+)", 세 번째 괄호는 "(\.[0-9a-zA-Z-]+)"이다.
첫 번째 괄호는 전체 패턴 문자열이므로 $regs[1]에는 사용자가 입력한 전자우편 주소가 저장되고, $regs[2]에는 두 번째 괄호 내 패턴에 일치하는 문자열이, $regs[3]에는 세 번째 괄호 내의 패턴에 일치하는 문자열이 저장된다.
예를 들어 사용자가 입력한 전자우편 주소가 jcafe@safelab.skku.ac.kr이라면 $regs[1]에는 "khjung@kornux.co.kr"이, $regs[2]에는 "\.[0-9a-zA-Z-]+"과 일치하는 문자열이 없으므로 null 값이, $regs[3]에는 "\.[0-9a-zA-Z-]+"과 일치하는 문자열이 ".kr"이 저장된다.

앞의 경우와 마찬가지로 17행의 패턴 문자열은 ereg() 함수 대신 eregi() 함수를 사용하여 다음과 같이 줄여 쓸 수 있다. 
ereg("(^[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*@[_0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*$")", $email, $regs)
eregi("(^[_0-9a-z-]+(\.[_0-9a-z-]+)*@[0-9a-z-]+(\.[0-9a-z]+)*$", $email, $regs)

HTML태그에 자동으로 하이퍼링크 걸기 ereg_replace() 함수를 이용하면 "http://", "ftp://"로 시작하는 HTML태그나 전자우편 주소의 패턴을 검사하여 자동으로 하이퍼링크를 걸어줄 수 있다. 즉, 사용자가 입력한 문자열중에 "http://mail.linuxet.co.
kr"와 같은 HTTP URL이 존재할 경우 이 문자열을 "<a href="http://mail.linuxer.co.kr>http://mail.linux.
co.kr</a>"로 바꾸어줌으로써 자동으로 링크를 걸어주는 것이다.
HTTP URL은 보통 다음가 같은 형태를 갖는다. 
http://www.yahoo.com
http://www.shinbiro.com/@linux
http://myhome.nets해.com/fathom
http://safelab.skku.ac.kr/~younicom/
http://safelab.skku.ac.kr/board/list.html?code=board&page_num=1
위의 예에서처럼 HTTP URL은 알파벳이나 숫자 또는 "./@~&=_"와 같은 기호 문자를 포함하므로 HTTP URL로 쓰일 수 있는 문자열에 대한 패턴은 다음과 같이 정의할 수 있다. 
http://([0-9a-zA-Z./@~?&=_]+)
FTP URL도 위의 HTTP URL과 마찬가지로 동일한 패턴을 적용할 수 있다.
다음의 예제를 보자.
<?

echo("<font size=\"2\">");

$http_url[] = "http://www.yahoo.com";
$http_url[] = "http://www.shinbiro.com/@linux";
$http_url[] = "http://myhome.netsgo.com/fathom";
$http_url[] = "http://safelab.skku.ac.kr/~younicom/";
$http_url[] = "http://safelab.skku.ac.kr/board/list.html?code=board&page_num=1";

$pattern_http = "http://([0-9a-zA-Z./@~?&=_]+)";

while(list($key, $val) = each($http_url)) {
  if($url = ereg_replace($pattern_http, "\\1", $val)) {
     echo("$url\n<br>");
  }
  if($url = ereg_replace($pattern_http, "<a href=\"http://\\1\">http://\\1</a>", $val)) {
     echo("$url\n<p>");
  }  
}

$ftp_url[] = "ftp://ftp.bora.net";
$ftp_url[] = "ftp://safelab.skku.ac.kr/pub/linux";
$ftp_url[] = "ftp://localhost/linux/php_3.0.12.tar.gz";

$pattern_ftp = "ftp://([0-9a-zA-Z./@~?&=_]+)";

while(list($key, $val) = each($ftp_url)) {
  if($url = ereg_replace($pattern_ftp, "\\1", $val)) {
     echo("$url\n<br>");
  }
  if($url = ereg_replace($pattern_ftp, "<a href=\"ftp://\\1\">ftp://\\1</a>", $val)) {
     echo("$url\n<p>");
  }  
}

$email_url[] = "yunka1018@netian.com";
$email_url[] = "9685351eng@linux.org";
$email_url[] = "92kdkang@shinbiro.com";

$pattern_email = "([_0-9a-zA-Z-]+(\.[_0-9a-zA-Z-]+)*)@([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)";

while(list($key, $val) = each($email_url)) {
  if($url = ereg_replace($pattern_email, "\\1@\\3", $val)) {
     echo("$url\n<br>");
  }
  if($url = ereg_replace($pattern_email, "<a href=\"mailto:\\1\@\\3\">\\1@\\3</a>", $val)) {
     echo("$url\n<p>");
  }  
}

echo("</font>");

?>
[예제3.11] ereg_replace() 함수를 이용한 HTML 태그 자동 인식 기능의 구현

위의 예제는 ereg_replace() 함수를 실행함으로써 "http://", "ftp://" 로 시작하는 URL 이나 전자우편 주소를 검사하여 HTML 태그로 하이퍼링크를 걸어주는 코드이다.
[예제3.11]의 5행에서 20행은 ereg_replace() 함수를 호출하여 5개의 http URL이 11행에서 정의한 패턴과 일치하면 해당 http URL1을 <a href="http:// ">http:// </a>와 같은 형탱의 하이퍼링크 태그로 치환하는 코드이다.

14행의 함수 호출 부분은 다음과 같다. 
$url = ereg_replace($patern_http, "\\1", $val)
이는 11행에서 정의한 패턴이 다섯 개의 http URL과 각각 일치하는지 조사하여 일치할 경우 해당 URL을 "\\1"로 치환한다. 여기서 치환 문자열 "\1"은 문자열 $val에서 패턴 문자열 내 첫 번째 괄호와 일치하는 문자열 부분을 저장하고 있는 대체 기호이다.
패턴 문자열 "http://([0-9a-zA-Z./@~?&=_]+)"의 첫 번째 괄호 내 패턴은 "[0-9a-zA-Z./@~?&=_]+"이므로 5행부터 9행까지 5갱의 http URL에서 이 패턴과 일치하는 문자열은 각각의 URL에서 "http://"를 제외한 부분임을 알 수 있다. 따라서 각 항목 첫 번째 경우와 같이 "http://"를 제외한 URL만이 출력된다.

17행의 함수 호출 부분을 보면 다음과 같다. 
$url = ereg_replace($pattern_http, "<a href=\"http://\\1\"> http://\\1</a>", $val
여기서는 치환시킬 문자열로 "<a href=\"http://\\1\">http://\\1</a>"를 정의하였다.
즉, 이는 http URL에 대한 하이퍼링크 태그임을 알 수 있다. 따라서 각 항목 두 번째와 같이 그 결과로 하이퍼링크가 출력된다.

22행엣 35행까지의 코드는 "http" 대신 "ftp"로 시작하는 문자열에 대한 코드로 "http://"가 "ftp://"로 바뀌었을 뿐 적용 패턴은 http URL의 경우와 동일하다.
37행에서 50행은 전자우편 주소를 검사하여 <a href="mailto:전자우편주소">전자우편주소</a>와 같이 전자우편 주소에 대한 하이퍼링크로 바꾸어주는 코드이다.

전자우편 주소에 대한 패턴 문자열은 41행과 같다.
$pattern_email = "([0-9a-zA-Z-]+(\.[_0-9a-zA-Z-]+))@([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)
전자우편 주소에 대한 패턴은 앞의 [예제3.10]에서 정의한 패턴과 동일하다.
47행에서는 ereg_replace() 함수의 치환 문자열로 아래와 같이 "<a href=\"mailto:\\1\@\\3\">
\\1@\\3</a>"를 주었다. 
$url = ereg_replace($pattern_email, "<a href=\"mailto:\\1\@\\3\">\\1@\\3</a>", $val)
위의 패턴 문자열에는 모두 네 개의 괄호가 있는데 첫 번째 괄호 내 패턴은 "([_0-9a-zA-Z-]+(\.[_
0-9a-zA-Z-]+)*)"이고 두 번째 괄호 내 패턴은 첫 번째 괄호 내에 있는 "(\.[_0-9a-zA-Z-]+)*)" 이며 세 번째는 "([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)", 네 번째는 세 번째 안에 있는 "(\.[0-9a-zA
-Z-]+)"이다.
예를 들어, 사용자가 입력한 문자열이 39행의 "92kdkang@shinbiro.com"일 경우 "\1"은 "92kdkang"이고 "\2"는 일치하는 문자열이 업으므로 null값을 가지며 "\3"은 세 번째 괄호 내 패턴과 일치하는 문자열이므로 "shinbiro.com"를, "\4"는 ".com"의 값을 갖는다. 즉 "\1"은 사용자 계정을 "\3"은 서버 이름을 저장한다. 따라서 전자우편 주소에 대한 링크를 걸어주기 위해 47행에서는 "\1"과 "\3"을 '@'로 연결 시켜주었다.

 

728x90
반응형

'study > TIP' 카테고리의 다른 글

php 문자열 함수  (0) 2012.02.27
fat32 usb convert to ntfs  (0) 2011.12.25
SmartEditor with upload  (0) 2011.12.09
프로젝트 산출 목록  (0) 2011.12.02
request path  (0) 2011.07.29