[Regular Expression] 정규표현식 문자 클래스와 문자열 매칭 기초
문자 집합이라고도 합니다. 대괄호([])로 문자(들)을 묶어서 표현하며, 대괄호 안의 집합에 포함된 문자 중 1개를 일치합니다.
[abcde] 와 같이 작성하며, 공백을 넣으면 공백 자체도 하나의 문자로 처리되어 일치합니다. [abcde]는 해당 문자가 “a”, “b”, “c”, “d”, “e” 중 하나이면 일치합니다.
/[lr]oad/는 “road”와 “load”를 모두 일치합니다.
“Overloaded vehicles damage roads” 문자열에 매칭하면 “load”, “road” 2개가 모두 매칭됩니다.
문자 범위
문자 클래스에 알파벳을 모두 포함하려면 아주 긴 문자 클래스를 작성해야 합니다.
연속되는 알파벳, 숫자는 “-”로 연결해서 처음과 끝의 문자만을 표시하는 방법으로 문자의 범위를 지정할 수 있습니다.
영문 소문자를 일치하려면 [abcdefghijklmnopqrstuvwxyz] 가 되어야 합니다. 연속되는 문자 범위를 짧게 표현하기 위해 “-”를 사용합니다.
[a-z]는 영문 소문자 전체가 됩니다. [a-zA-Z0-9]는 영문 대소문자, 그리고 숫자가 됩니다.
정규표현식 “[a-zA-Z0-9-_ #$%^@]”는 영문 대소문자, 숫자, 그리고 공백과 표시한 특수문자들을 일치합니다.
캐럿(^) 문자 주의
특수문자 중 캐럿(^]은 문자 클래스 맨 앞(“[^a-z]”)에 오면 특별한 의미(not을 의미)를 가지는 메타문자로 사용됩니다.
숫자 범위 [0-9]는 메타문자 “\d”로 대체해서 [a-zA-Z\d]로도 표현할 수 있습니다. 숫자만 선택하기 위해 [0-9]로 문자 클래스를 정의했으면 [\d]로 바꿔 사용해도 동일합니다. 문자 클래스는 문자 1개와 일치합니다. 주의해야 합니다.
부정 문자 클래스
문자 클래스 맨 앞에 캐럿 문자(^)를 사용하면 not의 의미가 적용되어 문자 클래스 안에 있는 문자가 아닌 모든 문자와 일치합니다. [^a-zA-Z]은 영문 알파벳이 아닌 모든 문자와 일치합니다.
캐럿 문자 일치를 위해 맨 앞에 캐럿 문자를 사용할 때는 역 슬래시로 이스케이프 (Escape) 해서 “\^”로 사용해야 합니다.
문자열 마지막 문자에 부정 문자 클래스 매치를 할 때는 특별히 주의할 점이 있습니다.
정규 표현식 /it[^a]/은 “quite”, “This is it!”에 일치하는 문자열이 있습니다. 이 정규표현식은 “it” + “a가 아닌 문자 한 개”와 일치합니다. “quite”는 “ite”, “This is it!”은 “it!”가 매칭됩니다.
반면, “exit”은 일치하지 않습니다. “it” 뒤에는 아무 것도 없는 “void” 이기 때문에 “a”인지 여부를 비교할 문자가 없습니다. “[^a]”은 “a”가 아닌 문자 한 개가 필수 입니다.
단, `exit\n`처럼 개행 문자로 줄 바꿈을 해서 여러 줄이 된 경우, 특수문자인 개행 문자(\n)가 “a”와 같은지를 비교를 할 수 있기 때문에 “it\n”이 일치합니다.
부정 문자 클래스를 사용해 넓은 범위의 문자 클래스를 간편하게 지정할 수 있지만 부정에 해당하는 문자까지 선택되는 단점이 있습니다.
앞서의 예에서 선택하려는 문자열이 “it”이라면(하지만 “it”뒤에는 부정 문자가 있어야 함. 즉 뒤에 “a”가 아닌 문자가 오면 “^a”는 버리고 “it”만을 매칭) 매칭한 문자열 결과를 얻은 후, 불필요한 부정 문자인 “a”를 잘라내는 자바스크립트 코드를 추가로 작성해야 합니다.
이런 번거로움을 줄이려면 /it(?!a)/처럼 “미리보기” 기능을 사용할 수 있습니다. “미리보기” 기능에 대해서는 뒤에서 자세히 설명합니다.
정규 표현식의 메타문자 중에는 부정 문자 표현의 축약형 표현인 것들이 여러 개 있습니다.
최대한 단축해서 일치 패턴을 표현하는 정규 표현식의 특성을 반영한 것으로 다음과 같은 것들이 있습니다.
메타문자 |
풀어 쓴 정규 표현식 |
설명 |
\D |
[^\d] 또는 [^0-9] |
숫자가 아닌 문자 |
\S |
[^\s] 또는 [^ ] |
공백이 아닌 문자 |
\W |
[^\w] 또는 [^a-zA-Z0-9] |
단어가 아닌 문자.
또는 영문 대소문자와 숫자가 아닌 문자. (한글 등 2바이트 문자 지원
안됨) |
단, [\S\D]는 [^\s\d]가 될 수 없습니다.
전자([\S\D])는 “모든 문자”가 일치하지만, 후자([^\s\d])는 “공백, 숫자가 아닌 문자”와 일치합니다. 비교식으로 표현하면 전자는 “not(공백) or not(숫자)”가 되고 후자는 “not(공백 or 숫자)”가 됩니다. 후자의 비교식을 풀어서 작성하면 “not(공백) and not(숫자)”가 됩니다. 착각하지 않도록 주의해야 합니다.
특수문자 표현
문자 클래스 내부의 특수문자, 또는 메타문자 일부는 일반 문자처럼 사용할 수 없습니다. 반드시 역 슬래시로 이스케이프를 해서 리터럴 문자로 적용해야 합니다.
문자 클래스 안에서 이스케이프를 해야 하는 문자는 닫는 대괄호(]), 백슬래시(\), 캐럿(^), 하이픈(-) 네 개입니다.
이스케이프를 해야 하는 특수문자들도 특정한 경우에는 이스케이프를 할 필요가 없습니다.
이스케이프 문자는 가독성을 현저히 떨어뜨리기 때문에 이스케이프가 필요 없을 경우 가급적 이스케이프를 하지 않는 것이 좋습니다.
특수문자 |
이스케이프 |
캐럿(^) |
문자 클래스 맨 앞에
올 때([\^])만 이스케이프를 합니다. 그 외의 위치 에서는 이스케이프가 필요 없습니다. |
하이픈(-) |
여는 문자 클래스([)
바로 뒤, 닫는 문자 클래스(]) 바로 앞에서는 이스케이프가 필요 없습니다. |
닫는 대괄호(]) |
문자 클래스 맨 앞에
오면 이스케이프가 필요 없습니다. |
그 외의 특수문자와 메타문자는 모두 리터럴 문자로 인식되므로 이스케이프 없이 그냥 사용합니다.
여는 대괄호 문자([)는 문자 클래스 안에서 리터럴 문자로 인식됩니다. 닫는 대괄호 문자(])만 주의하면 됩니다.
[\[a-zA-Z\]] 정규 표현식은 영문 대소문자 알파벳과 여는 대괄호, 닫는 대괄호 문자 중 한 개가 일치합니다.
한글과 유니코드 지원
정규 표현식은 2바이트 문자와 유니코드 표현을 모두 지원합니다.
한글만 선택하려면 /[가-힣]/으로 정규 표현식을 작성하면 됩니다. 한글 자모음까지 포함해 선택하려면 /[ㄱ-ㅎㅏ-ㅣ가-힣]/으로 일치합니다.
한글이 아닌 문자를 선택하려면 /[^ㄱ-ㅎㅏ-ㅣ가-힣]/으로 일치합니다. 한글이 아닌 것은 영문이 아닙니다. 한글이 아닌 것은 영문, 숫자, 특수문자, 기타 2바이트 언어권 문자 등을 모두 포함합니다. 주의해야 합니다.
영문으로만 입력 받고 싶다면 /a-zA-Z/로 일치해야지 /[^ㄱ-ㅎㅏ-ㅣ가-힣]/로 하면 안됩니다. 부정 문자 클래스는 필요한 경우에만 제한적으로 사용해야 합니다.
유니코드 문자는 \uFFFF 형태로 16진수로 표현합니다. \uFFFF 표현 방식은 자바스크립트에서 사용하는 유니코드 문자 사용 방식이며 펄 호환(PHP 포함) 정규 표현식에서는 \xFFFF 방식으로 표현을 해야 합니다.
정규 표현식 /\u20A9[\d,.]+/ 은 “오늘 환율은 ₩1,418 입니다.” 문자열에서 “₩1,418”를 일치합니다. \u20A9는 유니코드에서 원화 표시 기호를 나타내는 “₩”문자입니다.
유니코드 원화 표시
유니코드 원화표시에는 “U+20A9” 와 “U+FFE6” 2가지 문자가 있습니다. 앞의 것은 반각문자 (영문 1자 영역 차지), 뒤의 것은 전각문자(영문 2자 영역 차지) 입니다.
문자 클래스의 반복
문자 반복에 사용하는 메타문자 3가지(?,*,+)를 사용해 문자 클래스를 반복할 수 있습니다.
문자 클래스 오른쪽에 반복 메타문자를 붙여서 반복을 표시합니다. /[0-9]+/는 숫자가 1개 이상 연속으로 반복되는 것을 일치합니다. “010-1234-5678” 문자열에서 “010”이 일치합니다. “g”플래그로 전역 매치를 하면 [“010”, “1234, “5678”] 3개를 일치합니다.
문자 클래스 반복은 아주 중요하기 때문에 뒤에서 더 자세히 설명합니다.
확정되지 않은 숫자의 연속 반복을 일치하려면 “캡처 그룹(Capture Group)”을 사용해 /([0-9])\1+/g처럼 작성합니다.
캡처 그룹에 대해서도 뒤에서 자세히 설명합니다. 이런 방식으로 연속 반복 매칭을 하는 고급 기법도 있다는 정도만 알고 넘어갑니다.
/([0-9])\1+/g 정규표현식에서 \1은 앞의 소괄호(())로 결정된 숫자(캡쳐그룹)를 가져오는 역할을 하며, 가져온 숫자 값을 “+” 메타문자로 반복 매치를 합니다.
“+” 메타문자는 앞의 문자를 한 번 이상 반복 일치하므로 맨 앞의 숫자 한 개와 반복 일치 최소 한 개를 합해서 최소 2개의 같은 숫자가 일치하게 됩니다. “010-1222-3455” 문자열에서는 [“222”, “55”]가 매치됩니다.
아무 문자 한 개 선택(마침표 메타문자)
정규 표현식에서 마침표(.) 메타문자는 “아무 문자 한 개”를 나타냅니다.
딱 한가지 매칭하지 않는 예외는 특수문자인 줄 바꿈(\n) 문자입니다. 마침표 메타문자는 줄 바꿈 표시를 제외하고 모든 문자(한글과 유니코드도 한 문자로 처리) 한 개와 일치합니다. 부정 문자 클래스로 표현하면 /[^\n]/과 같습니다.
언뜻 만능이고 활용성이 좋아 보이지만, 모든 문자에 대응하는 강력한 능력을 가진 만큼 일치하면 안되는 문자까지 일치하는 문제를 만들어 내기도 합니다. 따라서 제한적인 경우에만 주의해서 사용해야 합니다.
윈도우와 유닉스의 줄 바꿈 문자 차이
파일 안에 줄 바꿈 표시를 저장하는 방식에 대한 오랜 역사적 차이때문에 발생하는 차이로 플랫폼에 따라 그냥 구분해서 사용해야 한다고 알고 사용하면 됩니다.
파일을 저장할 때 윈도우에서는 줄 바꿈 표시가 “\r\n”로 저장됩니다. 유닉스 환경 에서는 “\n”입니다.
“\r”은 정규 표현식에서 캐리지 리턴(Carriage Return) 문자로 별도로 구분되며, 실제로 정규 표현식 일치를 할 때도 별개로 매치를 합니다.
웹에서도 캐리지 리턴 문자는 별개로 처리하며 줄 바꿈은 “\n”으로 구분해서 처리를 합니다.
윈도우 환경에서 생성된 파일 데이터를 정규 표현식으로 일치할 때는 줄 바꿈을 “\r\n”으로 매치해야 줄 바꿈 사이에 걸친 문자열을 구분해서 매칭할 수 있습니다.
뒤에서 배우지만 “미리보기”로 정규 표현식 조건을 충족하는 문자열이 포함된 행 전체를 매치할 때도 윈도우 환경의 파일에서 가져온 데이터는 “\r\n”으로 매칭 조건을 설정해야 합니다.
파일 단위 데이터를 정규표현식 매치를 할 때는 자바스크립트 변수에 대입한 문자열 데이터를 다룰 때와는 달리 신경 써야 할 부분이 하나 더 있다는 점을 꼭 기억해 두어야 합니다.
한 줄 모드 플래그
마침표 메타문자에 대응하는 전용의 정규 표현식 플래그로 한 줄 모드 플래그(s)가 있습니다.
영문 소문자 “s”로 한 줄 모드를 켜게 되며, 마침표(.) 메타문자가 줄 바꿈까지 일치 하도록 합니다. 앞서 배웠지만 마침표 메타문자는 줄 바꿈 문자는 매칭하지 않습니다.
한 줄 모드를 켜고 전역으로 마침표 메타문자로 일치할 수 있는 문자를 매치(/./gs)하면 줄 바꿈을 포함해 문자열 안의 모든 문자가 매치됩니다.
별 의미는 없지만 마침표 메타문자에 한 줄 모드를 켜서 모든 문자에 일치하도록 하는 방법은 다른 방법으로도 만들 수 있습니다. 대표적으로 메타문자를 사용해서 /[\s\S]/g, /[\d\D]/g 로도 동일하게 구현할 수 있습니다. 플래그를 대신하는 이런 대체 구현 방법도 있다는 것만 알면 됩니다.
마침표(.) 메타문자 사용시의 문제들
모든 문자에 대응이 되므로 빠르게 정규 표현식을 작성할 수 있습니다.
“010-1234-5678”, “010/1234/5678”, “010.1234.5678”과 같은 여러가지 패턴의 연락처 정보를 일치하기 위해 /\d\d\d.\d\d\d\d.\d\d\d\d/로 매치를 하면 매치가 잘 됩니다.
그러나 이 정규 표현식은 “0101234567890”같은 문자열도 매칭을 합니다. 마침표 사용으로 인해 원하지 않는 문자열도 일치가 되는 문제가 생깁니다. 따라서 이 정규 표현식은 /\d\d\d[-/.]\d\d\d\d[-/.]\d\d\d\d/ 로 변경해야 적절하지 않은 문자열이 매치되는 문제를 피할 수 있습니다.
모바일 번호만을 찾는 경우에는 조금 더 정밀하게 일치를 할 수 있도록 /01\d[-/.]\d\d\d\d[-/.]\d\d\d\d/ 포맷으로 작성을 하는 것이 더 좋은 방법입니다.
수량 연산자를 사용하면 /01\d[-/.]\d{4}[-/.]\d{4}/로 더 최적화를 할 수 있습니다. 최적화 부분에 대해서는 뒤에서 더 자세히 배우게 됩니다.
자바스크립트는 변수에 문자열을 대입할 때 따옴표(‘’)와 쌍 따옴표(“”)로 감싸는 표현 모두를 지원합니다.
문자열 안에 따옴표가 사용된 문자열을 표시하려면 따옴표를 이스케이프 하는 대신 쌍 따옴표로 문자열을 감싸서 ‘그가 말했다. "I'm your father."’ 처럼 표시할 수 있는 대체 수단을 제공합니다.
문자열 안의 (쌍)따옴표로 감싼 문자열만을 일치하기 위해 정규 표현식을 ["'].*['"]로 사용하면 "I'm your father."를 매칭합니다.
정규식을 풀어서 설명하면 “2가지 종류의 따옴표 안에 아무 문자나 0개 이상 연달아 나오면 일치한다.” 입니다. 아주 그럴듯해 보이지만 다음 문자열에서는 [“프렌치프라이” 와 “코울슬로”]를 하나의 매치 결과로 일치합니다.
손님 “프렌치프라이”와 “코울슬로” 중 한 가지를 선택할 수 있습니다.
이 문자열에서 우리가 원하는 결과는 [“프렌치프라이”, “코울슬로”] 두 개여야 합니다. 그래서 마침표를 사용할 때는 주의해야 합니다.
수량자 “*”, “+”는 최대일치(Greedy)인 특징이 있기 때문에 마침표로 일치하는 문자(줄 바꿈 문자를 제외한 모든 문자)를 0개 이상 최대한으로 일치할 수 있는 만큼 일치시킵니다. 따라서 마지막 쌍 따옴표(“코울슬로” 뒤의 쌍 따옴표)가 나올 때까지 앞쪽의 쌍 따옴표(들)도 마침표 메타문자로 모두 일치해서 첫 매칭 결과에 포함하게 됩니다.
앞의 정규 표현식은 [“‘][^‘“\n]*[”’]로 수정해야 [“프렌치프라이”, “코울슬로”] 결과를 얻을 수 있습니다.
윈도우 환경의 파일 데이터를 매칭할 때는 \n이 아니라 \r\n을 사용해야 합니다.
최대일치(Greedy)라는 표현은 정규표현식 매칭에서 아주 중요한 개념으로 뒤에서 자세히 설명하므로 여기서는 넘어갑니다. 여기서는 일치할 수 있는 만큼 최대한 매칭을 한다 정도만 알면 됩니다.
많이 사용하는 문자(열) 메타문자 핵심 요약
정규 표현식에서 사용하는 미리 정의된 문자(열)을 선택하는 메타문자는 다음과 같은 것들이 있습니다. 정규 표현식을 작성할 때 가장 빈번하게 사용하는 것만 요약 했습니다.
기호 |
의미 |
[abc] |
[abc]는
[a-c]와 같습니다. 알파벳 소문자 전체는 [a-z]가 됩니다. “-”는 중간에 있는 아스키 문자 범위를 모두 포함합니다. 대괄호 안에 있는
문자(들)중 일치하는 문자를 매칭합니다. [a-o]는 “non-automate”
문자열에서 “u”를 매칭합니다. (하이픈은 매칭하는 문자가 아닙니다. 범위 지시자입니다.) 하이픈을 범위 지시자가
아닌 문자로 매칭 대상에 포함하려면 매칭 문자(들) 맨 앞, 또는 맨 뒤에 추가해야 합니다. [abc-]는 a
또는 b 또는 c 또는 - 문자를 매칭합니다. 알파벳 대소문자만 선택할 때는 [A-Za-z]로 선택할 수 있습니다. 알파벳 대소문자와 숫자만
선택할 때는 [A-Za-z0-9]로 선택할 수 있습니다. [A-Za-z0-9_-]는
특수문자를 제외한 모든 문자(Alphanumeric)을 선택합니다. 한글은 [가-힣]으로
선택합니다. |
[^abc] |
대괄호 안에 사용한
^는 not의 의미입니다. 대괄호 안의 abc 세 개의 문자가 아닌 나머지 문자를 선택합니다. 정규 표현식 /[^a-m]/은 “match”
문자열에서 “t” 문자 한 만을 매칭 합니다. 대괄호 바깥에서 사용할
때는 전체 문자열의 시작 위치를 표시하는 앵커 메타 문자로 사용됩니다. |
. |
임의의 문자 1개를
매칭합니다. 줄 바꿈 문자(\n,
\r, \u2028, \u2029)는 제외됩니다. |
\d |
숫자를 매칭합니다. [0-9]와 같습니다. |
\D |
숫자가 아닌 문자를
매칭합니다. [^0-9]와 같습니다. |
\w |
알파뉴메릭과 언더바
문자를 매칭합니다. [A-Za-z0-9_]
와 같습니다. |
\W |
알파뉴메릭(알파벳,
숫자, 언더바)이 아닌 문자를 매칭합니다. [^A-Za-z0-9_]
와 같습니다. |
\s |
공백 1개를 매칭합니다.
공백에는 탭, 폼피드, 라인 피드 또한 포함됩니다. |
\S |
공백이 아닌 문자
1개를 매칭합니다. |
\t |
탭 문자를 매칭합니다. |
\r |
캐리지 리턴 문자를 매칭합니다. |
\n |
줄 바꿈 문자를 매칭합니다. |
\ |
“\” 뒤에 표시한 문자를 이스케이프 처리해서 메타문자가 아닌 일반 문자로 매칭 되도록 합니다. |
a|b |
문자(열) 둘 중 하나라도 매치되면 매칭된 것으로 처리합니다. “|”는 or 연산자의 기능을 합니다. 왼쪽에서부터 먼저 비교를 해서 매칭된 결과를 반환합니다. |
- l a, b는 문자(열)입니다.