php 입문 | 텍스트 및 날짜 조작 | 정규 표현식

텍스트를 다룰 때, 피할 수 없는 것이 “정규식"라는 것이 있다. 이것은 “패턴"이라는 텍스트의 정렬의 법칙 같은 것을 준비하고 그에 따라 텍스트를 찾아 내거나 대체 할 수 있는 기능이다.

일반 검색 치환은 정해진 텍스트를 찾을 수 밖에 없다. 예를 들어 “PHP"라는 단어를 찾아라는 방식이다. 이에 비해 정규 표현식은 “어떤 법칙에 늘어선 텍스트인가"을 확인할 수 있다. 예를 들어 “3자리 숫자를 검색"이라든지, “a로 시작 s로 끝나는 텍스트 찾기” 같은 것을 할 수 있다.

정규식의 패턴은 “메타 문자(meta character)“라는 특수 기호를 사용하여 조합한다. 여기에는 다양한 기호와 규칙이 준비되어 있다. 아래의 목록에 목록을 올려 두었습니다.

※ 기본 메타 문자

기호 설명
\ 일반적인 회피 문자
^ 검색대상 (멀티 라인 모드에서는 행)의 처음)
$ 검색대상 (멀티 라인 모드에서는 행)의 끝
. 개행(줄바꿈)을 제외한 모든 문자와 일치
[] 문자 클래스
| 선택지의 시작
() 서브 패턴
? (의미 확장, 0 또는 1 회 반복, 반복을 최소화
* 0 이상의 반복
+ 1 이상의 반복
{} 최소 / 최대 반복 지정

※ 문자 클래스에서 사용할 수있는 특수 문자

메타 문자 설명
\ 이스케이프 문자
\b 백 스페이스
\f 페이지 넘김 (form feed)
\n 줄 바꿈 (new line)
\r 줄 바꿈 (carriage return)
\t 탭(tab) 문자
\d 숫자 하나 ([0-9]와 같다)
\s 공백 처리 문자 (공백, 줄 바꿈, 줄 바꿈, 탭 문자)
\w 숫자 + 알파벳 + 밑줄, 대소문자와 밑줄을 포함하는 모든 영숫자([a-zA-Z0-9_]와 같다
^ 부정
- 범위
  • 이 중 ^ - 이외는 문자 클래스 밖에서도 사용 가능하다.   ※ 문자 클래스 외부에서 사용하는 특수 문자
    메타 문자 설명
    \a 경보
    \c 컨트롤 기호 (이 후에 문자를 지정)
    \e 이스케이프
    \D 숫자를 제외한 문자 하나 ([^0-9]와 같다)
    \S 공백 문자가 아닌 모든 문자 ([^\f\n\r\t\v]와 같다)
    \W ‘숫자 + 알파벳 + 밑줄」이외 모든
    \b 단어의 구분
    \B 단어 경계 이외
    \A 텍스트의 시작
    \Z 텍스트의 종료 또는 개행
    \z 텍스트의 끝
    \ddd 8 진수로 ddd 문자
    \xhh 16 진수 hh 문자
     
    ※ 패턴 변경자
    메타 문자 설명
    :–:
    i 패턴 중의 문자는 대문자와 소문자를 매치
    m 검색 대상 문자열을 단일 행으로 구성된 처리
    s .를 줄바꿈을 포함한 모든 문자와 매치
    x 공백 문자을 무시
    e preg_replace()는 PHP 코드로 평가
    A 선두에서만 매치
    D $를 마지막에만 매치
    S 보다 시간이 걸렸다 분석을 실시
    U 매치 최단, 최장의 방식을 반대로 한다
    X Perl비 호환 기능의 이용
    u 패턴을 UTF-8로 한다
  • 이 문자들은 패턴의 성격을 규정하는 것으로, 패턴에 포함되지 않는다.

이를 “모두 기억해야 한다"라고는 말하지 않았다. 실제로 전부 기억 사용하고 있는 사람은 그리 많지 않을 것이다. 자주 사용할 것 같은 기호를 몇 가지 기억하는 것만으로도 정규식의 대단함은 실감할 수있을 것이다.

이 정규 표현식을 사용하기 위해 함수에는 몇 가지가 준비되어 있다. 우선은 “패턴 매치"와 “대체"에 대한 의미를 기억해두면 좋을 것이다.

패턴 매치용 함수

$변수 = preg_match(패턴, 텍스트, $변수);
$변수 = preg_match_all(패턴, 텍스트, $변수);

첫번째 인수의 패턴을 사용하여, 두번째 텍스트를 조사해, 패턴과 일치하는 (패턴에 부합하는 텍스트가 발견) 건수를 반환한다. preg_match는 처음 패턴 매치만, preg_match_all 모든 패턴 일치를 확인한다.

매우 흥미로운 것은 세번째 인수 준비하는 변수이다. 이것은 어떤 값을 지정하는 것은 아니다. 패턴 일치 한 결과를 이 변수에 얻을 것이다. 이는 다차원 배열의 형태로 되어 있고, 각각의 매치한 텍스트 정보를 모은다.

또한 네번째 인수로 패턴 매치에 대한 섬세한 플래그를 지정할 수도 있다. 이것은 본격적으로 정규 표현식을 사용하게 되었을 알아보도록 한다.

치환용 함수

$변수 = preg_replace(패턴, 대체 문자, 텍스트);

정규식을 사용하여 치환할 함수이다. 첫번째 인수는 패턴, 두번째 인수에는 대체 문자, 그리고 세번째로 조사의 대상이 되는 텍스트를 각각 전달한다. 반환값은 대체된 텍스트가 전달된다.

우선,이 3개를 알면 여러가지를 할 수 있게 될 것이다. 패턴 매치는 텍스트 데이터 중에서 특정 요소를 선택하고 (예를 들어, HTML 소스 코드에서 <a> 태그 링크 및 이메일 주소만 찾아 다닐수 있다), 치환할 수 있다면 절대로 정상적인 치환으로는 할 수 없는 복잡한 치환 처리를 할 수 있게 된다.

정규식 사용 예제

그럼 정규식 사용 예제를 작성해 보고 실행을 시켜 보자.

<?php
    if ($_POST != null){
        $url = $_POST['text1'];
        $lines = file($url);
        $data = implode($lines);
        // 패턴 매치
        $pattern = "/([\w-]+)@([\w\.-]+)\b/";
        $flg = preg_match_all($pattern, $data, $matchs);
        if ($flg != false){
            $result = "";
            foreach($matchs[0] as $key => $val){
                $result .= $val . "\n";
            }
        } else {
            $result = "없다.";
        }
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <form method="post" action="./index.php">
            <input type="text" name="text1" size="40" value="<?php echo htmlspecialchars($url); ?>"><br>
            <textarea name="area1" cols="30" rows="5"><?php echo $result; ?></textarea><br>
            <input type="submit">
        </form>
        <hr>
    </body>
</html>

여기에는 URL을 입력하면 해당 페이지의 텍스트를 얻어서 거기에서 이메일 주소만 찾아 표시시켜 보자.

위에 입력 필드에 http://~와 같은 식으로 조사하고 싶은 페이지의 URL을 입력하여 전송을 해보자. 그 페이지에 적혀있는 이메일 주소를 찾아서 아래의 텍스트 영역에 표시될 것이다.

여기에서는 먼저 file 함수를 사용하여 URL의 텍스트를 읽어 들여, 그것을 implode으로 하나의 텍스트로 정리한다. 그리고, 패턴을 사용하여 패턴 매칭을 실행하고 있다.

$pattern = "/([\w-]+)@([\w\.-]+)\b/";

이것이 준비한 패턴이다. 대체로, 여기에서 “헉, 정규식 어렵다. 무리야"라고 포기해 버리는 사람들이 많지만, 솔직히 그럴 필요는 없다. 정규식 패턴으로 인터넷으로 검색해 보면 이메일 주소 라든지, URL 든가, 비교적 자주 사용되는 패턴을 공개주는 사람이 많다. 그러한 패턴을 복사하여 사용하면 우선 패턴을 만들 수없어도 정규 표현식을 사용할 수 있다. 그리고 조금씩 스스로 공부하고 가면 나중에 도움이 될 때가 있을 거다.

$flg = preg_match_all($pattern, $ data, $ matchs);

여기가 패턴 매치를 실행하는 부분이다. 이 자체는 별로 어려운 것은 없다. 실행을 하면 이 $matchs라는 변수에 패턴 일치한 결과가 담긴다.

이 변수는 꽤 복잡한 구조로 되어 있다. 일치하는 텍스트를 얻으려면 인덱스가 0인 값을 꺼낸다. 여기에 연관 배열이 들어 있고, 그 값 부분에 찾아낸 텍스트(즉, 찾아낸 이메일 주소)가 저장되어 있다.

정리하면, 패턴 매치는 “결과의 배열 인덱스가 0인 연관 배열에서 값을 꺼낸다"라는 작업에서 찾아낸 모든 텍스트를 얻을 수 있다. 이것만 염두에 두면, 패턴 매치를 어느정도는 사용할 있을 것이다.

참조

이보다 더 자세한 내용을 알고 싶다면 아래 싸이트를 참고 바란다.




최종 수정 : 2021-08-27