정규 표현식(regular expression)은 다른 여러 언어와 마찬가지로 자바스크립트와 PHP에서도 지원한다. 정규 표현식을 쓰면 가장 강력한 패턴일치(pattern-matching) 알고리즘을 단 한 줄의 표현식으로 작성할 수 있다.

모든 정규 표현식은 반드시 슬래시(/)로 감싸야 한다. 이 슬래시 안에서는 특정 문자가 특별한 의미를 지니며, 이러한 문자를 메타문자(metacharacter)라 한다. 가령 별표(*)는 쉘이나 윈도우 명령 프롬프트에서 쓸 때와 의미가 비슷하다(하지만 의미가 완전히 같지는 않다). 별표는 "부합하려는 텍스트에 바로 앞의 문자가 0개 이상 존재할지도 모른다."라는 뜻이다.

예제

문자 클래스와 부정을 이해하면 이제 HTML 태그의 일치 문제를 해결할 더 나은 해법을 시도해 볼 준비가 됐다. 이 해법은 단일 태그의 끝을 지나가지 않지만 <em>과 </em>을 비롯해 아래처럼 속성이 포함된 태그도 일치한다.
<a href="www.mozilla.org">
해법은 다음과 같다.
/<[^>]+>/
이 정규 표현식이 아무렇게 입력한 것처럼 보여도 완벽히 유효하면서도 매우 유용한 표현식이다. 이 정규 표현식을 여러 부분으로 쪼개보자. 각 요소는 다음과 같다.
  • / - 정규 표현식을 나타내는 여는 슬래시.
  • < - HTML 태그의 여는 괄호. 이 괄호는 일치 대상이며, 메타문자가 아니다.
  • [^>] - 문자 클래스. ^>는 "닫는 괄호를 제외한 모든 문자와 일치한다"라는 뜻이다.
  • + - 이전 패턴인 [^>]와 일치하는 문자가 하나라도 있으면 임의 개수의 문자와 일치한다.
  • > - HTML 태그의 닫는 괄호. 이 문자는 일치 대상이다.
  • / - 정규 표현식의 끝을 나타내는 닫는 슬래시.
이번에는 흔히 쓰는 정규 표현식을 하나 살펴보자.
/[^a-zA-Z0-9_]/
위 정규 표현식에는 또 다른 두 가지 중요한 메타문자가 있다. 두 메타문자는 정규 표현식이 특정 위치에 나타나게 하여 정규 표현식의 위치를 지정한다. 캐럿(^)이 정규 표현식이 시작할 때 나타나면, 해당 표현식은 한 줄이 시작하는 위치에 나와야 한다. 그렇지 않으면 일치하지 않는다. 이와 비슷하게 달러 기호($)가 정규 표현식의 끝에 나타나면 해당 표현식은 한 줄의 끝에 나와야 한다.

이제 기초적인 정규 표현식 맛보기는 다음과 같은 질문에 답하면서 마무리하겠다. 한 줄에 정규 표현식 외에는 아무것도 없게 만들고 싶다면? 한 줄에 "Le Guin" 말고는 아무것도 없게 만들고 싶다면? 이전 정규 표현식에 처음과 끝을 나타내는 부분을 추가하면 이렇게 할 수 있다.
/^Le *Guin$/
메타문자 요약

다음은 정규 표현식에서 사용 가능한 메타문자를 보여준다.
  • / - 정규 표현식을 시작하고 끝낸다.
  • . - 줄 바꿈 문자를 제외한 임의의 한 문자와 일치한다.
  • element* - 요소와 0번 이상 일치한다.
  • element+ - 요소와 1번 이상 일치한다.
  • element? - 요소와 일치하지 않거나 한 번 일치한다.
  • [characters] - 대괄호 안에 포함된 한 문자와 일치한다.
  • [^characters] - 대괄호 안에 포함되어 있지 않은 한 문자와 일치한다.
  • (regex) - regex를 그룹으로 간주하여 갯수를 세거나, 다음에 오는 *, +, ?에 적용한다.
  • left|right - left나 right와 일치한다.
  • l-r - l과 r사이의 문자 범위와 일치한다(대괄호 안에 있을 때만)
  • ^ - 일치하는 패턴이 문자열의 처음에 있어야 함
  • $ - 일치하는 패턴이 문자열의 끝에 있어야 함
  • b - 단어의 경계와 일치한다.
  • B - 단어의 경계가 아닌 문자와 일치한다.
  • d - 숫자 문자 하나와 일치한다.
  • D - 숫자 문자가 아닌 문자와 일치한다.
  • n - 줄 바꿈 문자와 일치한다.
  • s - 공백 문자와 일치한다.
  • S - 공백 문자가 아닌 문자와 일치한다.
  • t - 탭 문자와 일치한다.
  • w - 단어 문자(a-z, A-Z, 0-9, _)와 일치한다
  • W - 비단어 문자(a-z, A-Z, 0-9, _이 아닌 문자)와 일치한다
  • x - x(x가 메타문자이더라도 x를 쓰고자 할 때 유용함)
  • {n} - 정확히 n번 일치한다.
  • {n,} - n번이나 그 이상 일치한다.
  • {min,max} - 최소 min, 최대 max 번 일치한다.
위에서 설명한 내용을 바탕으로 /[^a-zA-Z0-9_]/라는 정규 표현식을 다시 한번 살펴보면, 이 표현식을 /[^w]/으로 줄여 쓸 수 있음을 알 수 있다. 이는 단일 메타문자인 w(소문자 w)가 a-Z, A-Z, 0-9, _를 나타내기 때문이다.

사실 앞의 정규 표현식을 더 명확하게 표현할 수도 있는데, 메타문자 W (대문자 W)가 a-Z, A-Z, 0-9, _를 제외한 모든 문자를 나타내기 때문이다. 따라서 ^ 메타문자를 빼고 단순히 /[W]/로 쓸 수도 있다.이 정규 표현식이 어떻게 동작하는지 알려주기 위해 아래에 다양한 표현식과 그와 일치하는 패턴을 나열하였다.
  • r - The quick brown에서 첫 r
  • rec[ei][ei]ve - receive나 recieve (receeve나 reciive도 일치함)
  • rec[ei]{2}ve - receive나 recieve (receeve나 reciive도 일치함)
  • rec(ei)|(ie)ve - receive나 recieve (receeve나 reciive는 일치하지 않음)
  • cat - I like cats and dogs에서 cat 단어
  • cat|dog - I like cats and dogs에서 cat이나 dog라는 단어
  • . - . (.가 메타문자이므로 가 필요함)
  • 5.0* - 5., 5.0, 5.00, 5.000, 등
  • a-f - a, b, c, d, e, f 중 문자 하나
  • cats$ - My cats are friendly cats에서 마지막 cats
  • ^my - my cats are my pets에서 첫 my만
  • d{2,3} - 둘 또는 세 개의 숫자 (00에서 999까지)
  • 7(,000)+ - 7,000, 7,000,000, 7,000,000,000, 7,000,000,000,000 등
  • [w]+ - 하나 이상의 문자로 이루어진 단어
  • [w]{5} - 임의의 5글자로 이루어진 단어
일반적인 변경자

정규 표현식에서는 몇 가지 변경자(modifier)를 사용할 수 있다.
  • /g - "전역" 일치를 활성화. 바꾸기(replace) 기능을 쓸 경우 이 변경자를 쓰면 첫 번째 일치 결과만 바꾸는 것이 아니라 모든 일치 결과를 바꾼다.
  • /i - 정규 표현식이 대소문자를 구별하지 않음. 따라서 /[a-zA-Z]/ 대신 /[a-z]/i나 [A-Z]/i를 지정하면 된다.
  • /m - 캐럿(^)과 달러 기호($)가 대상 문자열 안의 줄 바꿈 전과 후와 일치하는 경우, 여러 줄 모드(multi-line mode)를 활성화. 보통 여러 줄 문자열에서 ^는 문자열의 시작과 일치하고, $는 문자열의 끝과 일치한다.
예를 들어, /cats/g라는 표현식은 "I like cats and cats like me"라는 문장에서 "cats"가 나타나는 곳과 모두 일치할 것이다. 이와 비슷하게, /dogs/gi라는 패턴은 "Dogs like other dogs"라는 문장에서 "dogs"("Dogs"와 "dogs")가 나타나는 곳과 모두 일치하는데, 이는 이러한 변경자를 함께 쓸 수 있기 때문이다.

자바스크립트에서 정규 표현식 사용하기(replace)
두 메서드를 비교하는 차원에서 아래 문장을 살펴보자. 아래 문장은 "cats"라는 단어가 전달한 문자열의 어딘가에 적어도 한번 나타나면 true를 반환한다.
document.write(/cats/i.test("Cats are fun. I like cats."))
하지만 다음 문장은 "cats"가 나타나는 곳을 "dogs"로 바꾸고 그 결과를 출력한다. 검색은 전역적으로(/g) 이루어져 모든 단어가 출현하는 곳을 찾고, 대소문자를 구별하지 않으므로(/i) 대문자로 쓴 "Cats"도 찾는다.
document.write("Cats are fun. I like cats.".replace(/cats/gi,"dogs"))
위 문장을 실행하면 replace의 한계를 확인할 수 있다. replace는 문자열을 정확히 사용하려고 하는 문자열로 바꾸기 때문에 첫 단어인 "Cats"는 "Dogs"가 아닌 "dogs"로 바뀐다.

PHP에서 정규 표현식 사용하기(preg_match, preg_match_all, preg_replace)
어떤 문자열에서 대소문자를 구별하지 않고 "cats"라는 단어가 나타나는지 검사하려면 아래처럼 preg_match를 쓰면 된다.
$n = preg_match("/cats/i", "Cats are fun. I like cats.");
PHP에서는 1을 TRUE로, 0을 FALSE로 사용하므로 이전 문장에서는 $n이 1로 설정된다. 첫 인자는 정규 표현식이고 둘째 인자는 일치할 텍스트이다. 하지만 preg_match는 실제로 더 강력하고 복잡한데, 이 함수는 일치할 텍스트를 나타내는 셋째 인자를 받기 때문이다.
$n = preg_match("/cats/i", "Cats are fun. I like cats.", $match);
echo "$n Matches: $match[0]";
셋째 인자는 배열(여기서는 $match)이다. 이 함수는 일치하는 텍스트를 첫 요소로 넣으므로 만약 일치가 성공하면 $match[0]에서 일치된 텍스트를 확인할 수 있다. 이 예제에서는 출력 결과를 통해 일치된 텍스트가 대문자로 시작함을 알 수 있다.
1 Matches: Cats
일치 위치를 모두 확인하고 싶다면 아래처럼 preg_match_all 함수를 쓰면 된다.
$n = preg_match_all("/cats/i", "Cats are fun. I like cats.", $match);
echo "$n Matches: ";
for ($j=0 ; $j < $n ; ++$j) echo $match[0][$j]." ";
전과 마찬가지로 $match를 함수에 전달했으며, $match[0]에는 일치된 결과가 할당되는데, 이번에는 2차원 배열의 부배열(sub-array)로 할당된다. 이 예제에서는 부배열을 보여주기 위해 for 루프를 이용해서 배열을 순회하였다.

문자열의 일부를 바꾸고 싶으면 아래처럼 preg_replace를 쓰면 된다. 이 예제는 대소문자를 구별하지 않고 "cats"가 나타나는 곳을 모두 "dogs"으로 바꾼다.
echo preg_replace("/cats/i", "dogs", "Cats are fun. I like cats.");
 
http://www.hanb.co.kr/network/view.html?bi_id=1653