1. 개념잡기

    일반화 시킨 표현. 이것을 정규표현이라고 요약할 수 있을 것 같다.
    다음의 과정을 너무 쉽다 생각말고 따라오길 바란다.

     - 감잡기

    "12354" -> 숫자
    "asdfasf" -> 알파벳
    두 가지의 간단정규표현을 만들었다. 실생활의 보기와 비추어보자.
    "길이가 3인 이름!"
    위의 표현은 길이를 표시하는 방법이 없다. 조금 더 발전시켜서 "알파벳{3}"이런식
    으로 길이를 표현할 수 있도록 한다. 그리고, "알파벳"란 것도 너무 길다 "알"
    이라고 한 글자로 표현한다. 그러면 "길이가 3인 이름"은
     "알{3}"으로 표시가 가능하다.
    길이가 10인 숫자는 "수{10}"
    "길이가 1인 알파벳이 나오고 그 다음에 길이가 3인 숫자가 나오는 문자열"! ->
    "알{1}수{3}"얼핏이나마 감이 올 것이다.
    "첫 글자는A, 그 다음은 아무 알파벳 5글자" -> "A알{5}"

     - 조금 더

    아이디는 대개 첫 글자는 영문이고 두 번째부터는 영문이나 숫자가 온다. 이것을
    표현하기 위해선 이것 들 중에 하나란 의미를 갖는 새로운 표현이 필요하다.
    "a,b,c,d 중에 하나" -> [abcd]
    응용하면,
    "알파벳이나, 숫자중 하나" -> [알수]
    "[" 안에 있는 문자들의 순서는 의미가 없으며, 그 표현은 (클래스라고 한다.)  
    결국 한 글자를 말한다.
    위에서 말한 "첫 글자는 영문, 두 번째 부터는 영문이나 숫자가 11자"를
    표현하면, "알[알수]{11}".
    그런데, 실제로 모든 아이디가 12자인 것은 아니다, 대개 4자부터 12자를 지원한다.
    새로운 표현이 등장한다. "몇 자부터 몇 자"
    "A가 3글자부터 12자" -> "A{3,12}"
    "알파벳이나 숫자가 1자부터 100자" -> "[알수]{1,100}"
    이제 아이디를 다시 정의하자.
    "첫 글자는 영문, 영문이나 숫자가 3자부터 11자" -> "알[알수]{3,11}"

    2. 표현식

    지금 까지의 규칙에서 설명한 용어를 실제 정규표현에서 사용하는 표현으로 바꾸고,
    다른 세부적인 옵션에 대해 알아보자.

    \ : 다음의 글자가 특별한 문자임을 나타낸다. 때론, 그 다음 문자 자체를 의미하기
    도 한다.
    보기를 들면, "\n"은 문자"\"과 문자"n" 두 글자와 매치되는 것을 의미하는 것이 아
    닌,
    새줄(New Line)을 의미하며, "\\"은 첫 "\" 다음 문자인 "\" 자체를 의미한다.
    즉, "\\"은
    "\"과 매칭된다.

    ^ : 입력문자열의 맨 처음을 의미한다. (맨 첫 글자가 아니라, 맨 처음이란 문맥적 의
    미를
    말한다. 아주 중요하다) 기본적으로 정규표현은 입력 문자열의 한 줄에만 적용된다.
    하지만, 옵션에 따라 여러줄에 적용할 수도 있다. 그럴 경우에는 "^"는  "\n"
    나 "\r"
    다음의 위치를 의미한다.

    $ : "^"는 반대로 입력 문자열의 맨 끝을 의미한다. 역시 여러줄에 정규표현이 적용

    경우에는 "\n"이나 "\r"의 앞의 위치를 의미한다.

    * : 이 문자 앞의 표현이 0번내지 무한번 반복될 수 있음을 말한다.
    보기를 들면, /a*/은 "a", "", "aaaa", "aaaaa"와 매칭된다.
    (0번이상은 없어도 된다는 것을 의미한다.)

    + : *와 같지만, 0번이상이 아니라 1번이상이라는 점을 제외하곤 /*/와 같다.

    ? : 앞의 표현이 0번 또는 1번. /do(es)?/는 "do", "does"와 매칭된다.

    {n} : 앞의 표현이 n은 음수가 아닌 정수이어야 하며, 앞의 표현이
    n번 매치되는 것을 말한다.

    {n,} : 앞의 표현이 n은 음수가 아닌 정수이어야 하며, n번 이상
    매치되는 것을 말한다.

    {n,m} : 앞의 표현이 n번 이상 부터 m번 이하까지 매칭되는 것을
    말하며, /*/는 /{0,}/과 같으며, /+/는 /{1,}/과 /?/는 /{0,1}/으로
    표현 가능하다.

    . : "\n"을 제외한 한 글자를 뜻한다. 만일 모든 글자를 표현하고
    싶다면("\n"마저도 합친) /[.\n]/을 사용하면 된다.

    x|y : x 또는 y와 매칭된다. 보기를 들면, /z|food/는 "z" 또는
    "food"와 매칭된다. /(z|f)ood/는 "zood" 또는 "food"와 매칭된다.
    (참고로 괄호는 묶어준 것 이상의 의미가 있다.)

    (패턴) : 해당 패턴과 매칭시키고, 그 부분을 특정 변수에 담는다.
    그 변수 이름은 JScript는 $0~$9까지의 변수에 저장이 되고(Perl과 같다.),
    VBScript에서는 SubMatches 컬렉션에 저장된다.
    괄호기호 자체와 매치시키고 싶다면? /\(/와 /\)/를 사용한다.

    (?:패턴) : 해당 패턴과 매칭은 시키지만, 그 부분을 특정 변수에
    담지 않는다. 왜 이게 필요할까?
    위의 보기에서 /(z|f)ood/는 "zood" 또는 "food"와 매칭된다고 했는데,
    단순히 매칭의 목적으로 사용했지만, "zood"의 경우 "z"가 $0 이란
    변수에 저장이 되고 말았다. 이러한 것을 막기 위해서 사용하는 것이
     (?:패턴)이다.

    (?=패턴) : (?:패턴)과 동일하지만, 패턴과 일치한 부분이후부터
    다음 매치가 일어나지 않고 패턴 앞부터 다시 매칭이 진행된다.
    즉, 룩업(lookup, lookahead)을 할 뿐이다. /Windows (?=95|98|NT|2000)/ 은
    "Windows 2000"의 "Windows" 부분과 매칭이 되며 다음 매칭은
    "2000" 다음 부터가 아닌 "Windows" 다음 부터 진행이 된다.

    (?!패턴) : (?=패턴)과 반대다. /Windows (?=95|98|NT|2000)/ 은
    "Windows 3.1"의 "Windows" 부분과 매칭이 된다.



    [xyz] : "["안에 있는 표현중 하나를 의미한다.

    [^xyz] :  "["안에 있는 표현을 제외한 것중 하나를 의미한다.
    "[^abc]"는 "plain"의 "p"때문에 매칭된다.

    [a-z] : "a"부터 "z" 까지의 문자중 하나

    [^a-z] : "a"부터 "z" 까지의 문자를 제외한 하나

    \b : 단어의 경계(단어와 공백, "\n", "\r"의 사이)와 매칭된다.
    보기를 들면, "er\b"는 "never"와는 매칭되지만, "verb"와는 매칭되지 않는다.

    \B : 단어의 경계가 아닌 것과 매칭된다. "er\B"는 "verb"와는
    매칭되지만, "never"와는 매칭되지 않는다.

    \cx : Ctrl+x 키와 매칭된다. "\cc"는 Ctrl+C와 매칭된다. x의 범위는
    [a-zA-Z]이며, 만일 이 이외의 문자를 사용한다면 "\c"는 "c"와 동일하다.

    \d : [0-9]와 같다.

    \D : [^0-9]와 같다. 참고로 대문자는 소문자의 반대 의미를 갖는다.

    \f : 폼피드(form-feed) 문자를 의미하며, "\x0c"와 "\cL"과 동일하다.

    \n : 새 줄(newline)를 의미하며, "\x0a"와 "\cJ"와 동일하다.

    \r : 캐리지 리턴(carriage return)을 의미하며, "\x0d"와 "\cM"과 동일하다.

    \t : 탭. "\x09", "\cI"과 동일

    \v : 버티컬 탭. "\x0b", "\cK"과 동일

    \s : 화이트스페이스를 의미한다. 화이트스페이스란 공백, 탭, 폼피드,
    캐리지리턴등을 의미한다. [ \f\n\r\t\v]과 동일("\f"앞에 공백이 있다. 주의!)

    \S : "[^ \f\n\r\t\v]"

    \w : "_"를 포함한 일반적인 단어에 사용되는 문자를 말한다.
    "[A-Za-z0-9_]" 과 동일

    \W : "[^A-Za-z0-9_]"

    \xn : n은 2자리 16진수이며, 해당 16진수 코드와 매칭된다. "\x412"는 16진수
    41은 "A"이기 때문에 "A2"와 매칭된다.

    \num : 캡쳐한 매칭을 가리킨다(백레퍼런스, backreference).
    "(.)\1"은 연속된 두개의 문자열을 의미한다.
    \n : "\1"은 위에서 캡쳐한 매칭(backreference)를 가리킨다고 했는데,
    만일 이 패턴앞에 어떠한 n개의 캡쳐한 표현이 있다면 백레퍼런스이지만,
    그렇지 않은 경우에는 8진수로 간주하여 해당 코드의 문자와 매칭된다.

    \un : n은 4자리 UNICODE 이다. "\u00A9"은 copyright 심볼인 "ⓒ"와 매칭된다.


    3. greedy, non-greedy

    ? : 앞에서 설명했는데, 왜 또? 라고 생각할 것이다.
    ?은 문맥에 따라 특별한 의미를 갖는다.
    패턴 "o*"는 "foooood"와 매칭된다. 당연하다! 하지만, "f"앞의 "o"와
    매칭되는 것이 아니다!! "ooooo"와 매칭된 것이다. 즉, 기본으로
    정규표현 매칭은 가장 큰 범위를 선택한다. 이것을 greedy하다고 한다.
    하지만, 때론 작은 범위에 매칭시킬 필요가 있을 경우가 있다.
    (이의 적절한 보기는 잠시 후에 나온다.) "o*?"가 방금 말한
    non-greedy 매칭이다.
    수량관련 문자인 "*", "+", "?", "{n}", "{n,}", "{n,m}" 다음에 "?"가
    나오면 non-greedy 매칭이된다.
    잠시, 위에서 "o*?"가 "o"와 매칭된다고 했는데 이상하게 생각한 분이
    있었을 것이다. 맞다. "o*?"는 ""와 매칭되었다. "*"는 0개이상임을
    잊어선 안된다. "o+?"가 "o"와 매칭된다.

    4. 보기

     - 웹 주소

    http://msdn.microsoft.com:80/scripting/default.htm
    위의 주소를 표현할 수 있는 정규표현은 아래와 같다.

    /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/
    $1 : http
    $2 : msdn.microsoft.com
    $3 : 80
    $4 : /scripting/default.htm


     - 중복된 단어를 하나로

    중복된 영어단어를 하나로 합치기 위해선, 우선 단어를 찾아야한다.
    그리고 단어는 앞 뒤가 단어의 경계이어야한다. (말이 참 이상하지만..)
    따라서, 아래와 같은 1차 정규표현을 얻을 수 있다.

    /\b([a-z]+)\b/

    연속해서 동일한 두개의 단어... 앞에서 캡쳐한 표현을 다시 활용하면 된다.
    그리고, 단어와 단어 사이엔 화이트스페이스가 있다.

    /\b([a-z]+)\s+\1\b/

     - HTML 태그 제거

    HTML문서에서 태그를 제거한 문서를 추출하고자 한다.
    태그는 "<"와 ">"로 감싸여 있다.

    /<.*>.*</.*>/

    그런데, 위의 정규표현을 HTML문서에 적용하여 해당 패턴을 "",
    빈문자열로 바꾸면 문서는 빈 문서가 되고 만다.

    <html>
    <title>...</title>
    <body>
    <font>.... </font>
    ...
    </body>

    greedy한 매칭이 기본값이라고 위에서 언급을 했다. 따라서,
    위의 HTML 문서를 보면, <html>....</body>로 생각할 수 있다.
    따라서, 문서 전체가 사라지는 것이다. 이것을 막기 위해선 "*"뒤에 "?"를
    추가하면 된다.                            

    /<.*?>.*?</.*?>/

    아직 끝나지 않았다. :)

    좀더 정제를 한다면, 올바른 HTML 문서는 <태그명>과 </태그명>이
    서로 일치한다. 이것도 적용한다면,

    /<.(*?)>.(*?)</\1>/

    위의 $1에 해당되는 부분을 좀 더 생각해보면, ">"를 제외한 문자로
    볼 수 있다. 따라서 최종적으로 아래와 같이 정리된다.

    /<(\w+)[^>]*?>(.*?)</\1>/

     - URL

    /(?:^|")(http|ftp|mailto):(?://)?(\w+(?:[\.:@]\w+)*?)(?:/|@)([^"\?]*?)(?:\?
    ([^\?"]*?))?(?:$|")/


     - float 상수

    /^(((+|-)?\d+(\.\d*)?)|((+|-)?(\d*\.)?\d+))$/  -1.1 1.1 .9 .8

    Posted by 부니기