선생님을 위한 프로그래밍 수업

정규 표현식

토픽 선생님을 위한 프로그래밍 수업 > 웹 애플리케이션 만들기 > PHP

정규 표현식

 

정규 표현식(正規表現式,Regular Expression)은 문자열을 처리하는 방법 중의 하나로 특정한 조건의 문자를 '검색'하거나 '치환'하는 과정을 매우 간편하게 처리 할 수 있도록 하는 수단이다.

선행지식

정규 표현식은 이것 자체로도 한권의 책이 필요할 정도로 방대하다. (물론 간단한 정규 표현식을 배우는데는 큰 노력이 들지 않는다.) 정규 표현식에 대해서 잘 모른다면 '정규 표현식 패턴들' 수업을 먼저 보고 이후의 내용을 학습하는 것을 권장한다.

표현식

http://ult-tex.net/info/perl/

PHP와 정규표현식

PHP의 정규표현식은 구분자(delimiters)로 시작해서 구분자로 끝을 내야한다. 구분자는 보통 슬래쉬(/)를 사용하지만 꼭 그래야 하는 것은 아니고 해쉬(#)와 같이 알파벳과 백슬래쉬 그리고 공백이 아닌 문자를 사용하면 된다. 아래의 그림에서 강조표시한 부분은 모두 구분자가 될 수 있는 문자들이다. (참고)

닫히는 구분자 뒤에는 옵셥(Internal Option)이 위치할 수 있는데 옵션에 따라서 정규표현식이 다르게 동작한다. 아래는 대소문자를 구분하지 않는 'i'와 줄바꿈 문자에 따라서 텍스트의 행을 구분하도록 하는 'm'을 적용한 예다. (참고)

PHP는 UNIX 스타일의 정규표현식인 ereg와 Perl 스타일의 정규표현식인 preg를 지원한다. 이 중에서 ereg는 폐지 예정(Deprecated)이기 때문에 사용해서는 안된다. (참고)

preg_match

검색을 수행하고 일치하는 내용을 반환한다.

i는 패턴 매칭을 할 때 대소문자를 구분하지 않도록 한다.

<?php
if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}
?>

 \b는 단어의 경계를 의미한다. 그렇기 때문에 \b로 감싸진 web은 web이라는 독립된 단어를 의미한다. website는 web과 site가 결합된 단어이기 때문에 이 조건에 해당하지 않는다.

<?php
if (preg_match("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}

if (preg_match("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}
?>
<?php
$subject = 'coding everybody http://opentutorials.org egoing@egoing.com 010-0000-0000';
preg_match('~(http://\w+\.\w+)\s(\w+@\w+\.\w+)~', $subject, $match);
var_dump($match);
echo "homepage:".$match[1];
echo "<br />";
echo "email:".$match[2];
?>

<?php
// get host name from URL
preg_match('@^(?:http://)?([^/]+)@i',
    "http://www.php.net/index.html", $matches);
$host = $matches[1];

// get last two segments of host name
preg_match('/[^.]+\.[^.]+$/', $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>

 

<?php

$str = 'foobar: 2008';

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

/* This also works in PHP 5.2.2 (PCRE 7.0) and later, however 
 * the above form is recommended for backwards compatibility */
// preg_match('/(?<name>\w+): (?<digit>\d+)/', $str, $matches);

print_r($matches);

?>

 

 

preg_replace

검색한 다음 치환명령을 수행한다. (참고)

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

 

<?php
$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의 값을 정의한 순서 때문이다. $replacements의 인덱스 값을 2,1,0 순으로 정의했는데 php는 인덱스 값의 순서에 따라서 치환을 하는 것이 아니고, 배열의 값이 생성된 순서대로 치환을 하기 때문에 $patterns[0]의 카운터 파트너는 $replacements[0]이 아니라 $replacements[2]가 된다. 필자도 나중에 알게 된 사실이다. 
<?php
$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');
?>

 

댓글

댓글 본문
  1. 드림보이
    2022.01.20. 정규 표현식 파트 수강완료
  2. ggyuker
    2022.01.04 수강완료 80% 이해완료
  3. jeisyoon
    2021.07.30 Regular Expression - OK

    어렵기는 했지만 재미 있네요. 감사합니다 ^^
  4. 준서
    감사합니다 ㅎ
  5. 호두
    2019 02 13 고맙습니다
  6. 박인호
    12-13
    수강완료.
    감사합니다.
  7. 쿠반
    치환 1/2에서의 정규식의 대체 쪽 부분이 이해가 가지 않아서 자료를 찾아봤습니다.


    제가봤을때는 강의에서 쓰인 $1은 캡처 그룹의 인덱스입니다.
    그리고 캡처 그룹이 숫자로 구성된 경우에는 ${name}은 번호가 매겨진 그룹으로 해석됩니다.

    대체의 $number는 캡처 그룹의 배열에서 인덱스 이고 여기서 ${name}은 연관배열의 문자를 나타내는 것 인데,
    1/2 예제에서는 연관배열의 문자가 지정이 안되있으므로 ${1}을 써줘도 $1로 인식되는 것 같네요.

    PHP 사이트에서 예제가 그냥 replacement = $1 1,$3 로 되어있었다면 머리 아플 일 없이 좋았을텐데ㅠ

    참고 : https://msdn.microsoft.com......110).aspx
  8. 엽스
    정규표현식 짱 입니다.
    좋은 강의 잘 보고 갑니다. 정말 감사해요.
  9. 송성태
    다시 한번 추상화군요.
    코드를 더 단순하게..
    정규 표현식을 왜 쓰는지 이해는 했습니다.
    다시 한 번 더 보아야 겠습니다.
    감사합니다!
  10. 다시시작
    일단 쭉 보기만 한...나중에 다시 봐야 할 강의...
  11. 방대한 코드를 짜지 않더라도 정규표현식은 간단한 회원가입에서도 많이 쓰입니다.
    대화보기
    • kimjs9105
      정규표현식 참 어렵네요... 며칠째 보고있는건지.. 일단 한번씩 다 봣으니 넘기고 다시오겠습니다~뿅!
    • 초보
      오타가 있네요 정규표현식 두번째 문단 첫줄에 옵션이 옵셥으로 오타나있어요
    • sheis
      잘 봤어요^^
    • meek
      감사합니다~ 어렵긴 어렵네요 ㅜㅜ
    • 김세창
      감사합니다!^^ ㅎㅎ
    • 삐꾸돼지
      이 부분은 나중에 보기로 하고 넘기겠습니다.!
    • park
      코딩을 배우기 시작한지 얼마 지나지 않은 입장에서
      정규표현식을 써야할만큼 방대한 코드를 짤 일이 없을 것이기 때문에
      우선 제낍니다
    • NamJin Kim
      아 감사합니다
    • JustStudy
      고맙습니다.
      말씀대로 실무에서 많이 사용해야 익혀질 수 있겠습니다.
    • 치환 1/2 강의의 $replacement = '${1}1,$3'; 에서요

      ${1}1에서 { } 숫자가 배열안에 key값을 의미하자나요
      위에처럼 했을때 해당키값의 데이타를 찾아서 { }옆에 입력된 값으로 치환이 되는데요..

      즉, ${1}1처럼 할경우
      april을 april1 로 바꾸는게 아니라, april값 자체를 1로 바꿔서 반환합니다.

      이건 제꺼 버전이 낮아서 그런건지..이게 맞는건지 모르겠내요
    • jemi
      첫번째 강좌에서
      /php/i

      preg_match의 첫번째 인자 설명중

      /(슬래쉬)를 \(역슬래쉬)라고 실수로 말하신것같네요!!
    • 엔트
      정말 감사합니다
      좋은 강의 잘듣고있습니다
      머리에 쏙쏙!
    • 진심으로 감사드립니다~^^
    • 캠프리핸드
      php 안에서 자바를 넣는경우 어떻게 연결을해야되나요? 아무리 해도 자바스크립트가 적용이 안됩니다.


      또 질문입니다.
      위에 설명해주신것은 php 어떤경우에 적용되나요?
      wordpress에서 php를 footer header 등등 이렇게만 배웠는데

      저부분은 생소합니다.
    • 이용주
      어엇! 막 엄청난 지식이 머리에 들어 왔는데 이것을 내가 못 꺼내는 그런 느낌이에요. 설명을 들으면 그렇구나 하겟는데 코딩을 시작하면 백지가 되네요,...... 이번 토픽은 눈으로만 익히고 다시 돌아 올게요`~ ;;;
    • 첫 동영상에서 ctrl+f로 원하는 문장을 찾고 replace 를 단축키를 사용하셔서 어떻게 나오게 하는지 모르겠는데 단축키좀 알려주세요!
    • 플라이곰
      나도 행복합니다.
      대화보기
      • 육점이
        버전이 달라서 그런건지 몰라도, ~를 찾을때 포함시켜서 찾고 결과에서는 빼는 기능의 정규표현식이
        (?=~)로 해야 작동하고
        참조로 되어있는 코드(?:~)로하면 작동이 되지를 않아요ㅠㅠㅠ
      • 무성한털
        $replacements 는 index 값과는 상관없이 위에서 순서대로 배열을 처리하는 것 같네요^^;;
      • 샤핀
        강의로 그냥 볼때는 설명해 주시니까 쉽게 이해가 되는데, 꽤 많은 경험이 필요할 것 같네요.
        좋은 강좌 감사합니다.
      • 샤핀
        음.. 첫 동영상 강좌에 10:12 지점에서 /foo bar/ <-- 여기서 이건 그냥 슬러시 인거 같은데 \ 역슬러시로 설명하고 계신거 같아요.
        그냥 의역하긴 하지만 사소한 옥의 티 같아서 ^^;;
      • 0132h
        어렵지만 항상 잘 설명해주셔서 감사합니다...
        열공열공!!
      • 별모모
        예제에서 $replacements[0]처럼 배열 인덱스를 지정하여 값을 변경한 것은 맞습니다. 다만, "배열"은 순서를 강제하지 않습니다. 변경된 인덱스의 값을 순서대로 출력하기 위해서는 ksort($replacements);처럼 정열시켜서 출력하면 제대로 출력될 것입니다. (코드참조: http://ideone.com/xyRBMN)

        $replacements = array();
        $replacements[2] = 'bear';
        $replacements[1] = 'black';
        $replacements[0] = 'slow';

        echo $replacements[0];
        echo $replacements[1];
        echo $replacements[2]

        [출력 값]
        slowblackbear
        대화보기
        • egoing
          예제 하단에 이유를 적어두었습니다. 제가 실수한 부분이네요.
          대화보기
          • egoing
            서리님 덕분에 원인을 찾았습니다. 알려주셔서 감사합니다. 이런 페이크에 속다니 부끄럽습니다. ^^
            대화보기
            • egoing
              제가 예제를 충분히 파악하지 못한 상태에서 발생한 문제네요. 말씀하신 예제의 하단에 이유를 적어두었습니다. 죄송합니다!
              대화보기
              • 서리
                미처 몰랐었네요... php자체에서 그거를 자동으로 정렬을 해서 출력해주지를 못하나 보네요..;;

                ksort($replacements); 이 구문을 추가해야 정렬하여 출력 할 수 있나보네요

                http://kr1.php.net......php
                대화보기
                • 찍찍이얌
                  예제에서요~
                  replacement[] <- 괄호안의 값이 맞는거에요?

                  The slow black bear jumped over the lazy dog.
                  이렇게 치환될것 같은데요...
                  아름소리님의 질문과 같아요~
                  이유를 좀 알려주세요~~~
                • 아름소리
                  좋은 강의해주셔서 정말 감사합니다.

                  한가지 질문이 있습니다.
                  동영상 'PHP - 정규표현식 치환2'의 7.php 에서 입력과 출력이 다음과 같습니다.
                  input : 'The quick brown fox jumped over the lazy dog.'
                  output : 'The bear black slow jumped over the lazy dog.'

                  그런데, 'quick' => 'slow', 'brown' => 'black', 'fox' => 'bear'로 치환되니까,
                  'The slow black bear jumped over the lazy dog.'로 되어야 할것 같은데, 다른 결과가 나옵니다.

                  왜 그런건가요?
                • 자유로운푸른곰
                  이런좋은 곳을 찾아서 행복합니다.
                • egoing
                  경배님 말씀 고맙습니다!
                  대화보기
                  • egoing
                    감사합니다 ^^
                    대화보기
                    • 학생
                      감사합니다.~ (_ _
                      정말 잘배우고 있습니다.~
                    • 노경배
                      정말 이고잉님의 정성이 느껴지니다.