정규 표현식
문자열은 카카오톡봇 뿐만 아니라 모든 개발에서 중요한 데이터 타입입니다. 문자열은 문자들의 집합이 되는 타입으로, 일련의 문자들을 다루는데 중심이 됩니다. 이번 편에서는 문자열을 다루는 강력한 도구인 정규 표현식(regular expression)에 대해 배웁니다.
정규 표현식은 문자열에서 특정 패턴을 찾거나, 대체하거나, 분리하는 등의 작업을 수행할 수 있게 해줍니다. 정규 표현식을 사용하지 않더라도 해당 기능을 구현할 수 있지만, 다소 복잡해집니다. 정규 표현식을 사용하면 이러한 작업을 간결하고 효율적으로 수행할 수 있습니다.
문자열이 유효한 주민등록번호의 형식인지를 검사하는 예제를 통해 설명하겠습니다. 주민등록번호는 6자리 숫자와 7자리 숫자가 하이픈(-)으로 구분된 패턴의 문자열입니다.
123456-1234567
우리가 정규 표현식 없이 패턴을 검사하려면 문자열을 분리하고 각 부분이 숫자인지 확인해야 합니다.
function isVaildRRN(rrn) { // 앞 6자리 검사 for (let i = 0; i < 6; i++) { if (!Number.isInteger(rrn[i])) return false; } // 하이픈(-) 검사 if (rrn[6] !== '-') return false; // 뒤 7자리 검사 for (let i = 7; i < 14; i++) { if (!Number.isInteger(rrn[i])) return false; } return True; }
위 방법은 정규 표현식을 제외한 방법 중에서도 최선의 방법은 아니지만, 정규 표현식에 비해 코드가 길고 복잡합니다. 정규 표현식을 사용하면 아래와 같이 간단하게 구현할 수 있습니다.
function isVaildRRN(rrn) { const regex = /^\d{6}-\d{7}$/; return regex.test(rrn); }
정규 표현식 생성하기
JavaScript에서 정규 표현식은 RegExp
객체입니다. 그러므로 아래와 같이 정규 표현식을 만들 수 있습니다.
const regex = new RegExp("^\\d{6}-\\d{7}$");
하지만 이보다 더 좋은 방법이 있습니다. 우리가 문자열을 만들 때 new String()
대신 ""
나 ''
을 사용하는 것처럼, 정규 표현식도 더 간단한 리터럴을 제공합니다.
슬래시(/ /
) 사이에 정규 표현식의 패턴을 작성합니다.
const regex = /^\d{6}-\d{7}$/;
첫번째 방법에서는 정규 표현식의 패턴을 문자열 리터럴로 표현해 \d
를 표현할 때 역슬래시를 두 번 입력해야 했습니다.
하지만 두번째 방법은 정규 표현식을 위한 리터럴로 표현하므로 역슬래시를 한 번만 입력해도 됩니다. 정규 표현식에서 \d
의 의미는 아래에서 확인할 수 있습니다.
정규 표현식의 패턴 구문
정규 표현식의 패턴은 다양한 구문을 사용하여 문자열의 특정 패턴을 정의합니다. 그러므로 각 구문이 어떤 의미를 가지는지 알아야 합니다. 하지만 이를 암기하려고 하지는 마세요. 필요할 때마다 참고하며 자연스럽게 숙지하는 것을 추천합니다.
문자 클래스
문자 클래스(character class)는 숫자, 알파벳 등 특정한 종류의 문자를 가리키는 구문입니다.
정규 표현식의 문자 클래스 | |
---|---|
[...] | 괄호 안에 있는 각 문자들을 가리킵니다.
문자 사이에 하이픈(
하이픈을 가장 처음 또는 가장 끝에 위치시킬 경우, 하이픈은 범위 지정을 위한 기호가 아닌 하이픈 문자 자체로 취급합니다.
괄호 안의 맨 처음 글자가
|
. | 텍스트 줄의 끝을 나타내는 문자(
|
\d | 아라비아 숫자 문자를 가리킵니다.
|
\D | 아라비아 숫자 문자를 제외한 문자를 가리킵니다.
|
\w | 기본 라틴 알파벳과 아라비아 숫자, 언더바(
|
\W | 기본 라틴 알파벳과 아라비아 숫자, 언더바(
|
\s | 공백 문자(스페이스, 탭, 폼 피드, 라인 피드, 그 외 유니코드 공백 문자)를 가리킵니다.
|
\S | 공백 문자(스페이스, 탭, 폼 피드, 라인 피드, 그 외 유니코드 공백 문자)를 제외한 문자를 가리킵니다.
|
\t | 탭 문자를 가리킵니다. |
\r | 캐리지 리턴을 가리킵니다. |
\n | 줄바꿈 문자를 가리킵니다. |
\v | 수직 탭 문자를 가리킵니다. |
\f | 폼 피드를 가리킵니다. |
[\b] | 백스페이스(backspace) 문자를 가리킵니다. |
\0 | NUL 문자를 가리킵니다. (오타가 아닙니다!) |
\c X | 캐럿 표기법을 사용해 제어 문자를 가리킵니다. |
\x hh | 2자리 16진수 코드 |
\u hhhh | 4자리 16진수 코드 |
\ |
|
x|y | 문자열 x 또는 y를 가리킵니다.
|
Assertion
Assertion은 특정 위치에 있는 문자열을 가리키는 구문입니다.
정규 표현식의 assertion | |
---|---|
^ | 문자열의 맨 처음에 존재하는 문자열를 가리킵니다.
|
$ | 문자열의 맨 끝에 존재하는 문자열을 가리킵니다.
|
\b | 단어의 경계에 존재하는 문자열을 가리킵니다.
|
\B | 단어의 경계가 아닌 곳에 존재하는 문자열을 가리킵니다.
|
x(?=y) | "y"가 바로 다음 글자로 오는 "x"를 가리킵니다.
|
x(?!y) | "y"가 바로 다음 글자로 오지 않는 "x"를 가리킵니다.
|
(?<=y)x | "y"가 바로 앞 글자인 "x"를 가리킵니다.
|
(?<!y)x | "y"가 바로 앞 글자로 오지 않는 "x"를 가리킵니다.
|
그룹/역참조
그룹은 정규 표현식의 특정한 패턴을 구분하는 장치입니다. 그룹의 패턴과 일치하는 값을 기억(캡쳐)해 사용하기도, 정규 표현식 내에서 역참조할 수도 있습니다.
정규 표현식의 그룹/역참조 | |
---|---|
( x ) |
주의 그룹을 캡쳐할 경우 성능 저하가 있을 수 있습니다. 캡쳐할 필요가 없을 경우 비캡쳐 그룹을 사용하세요.
|
(?< Name > x ) |
|
(?: x ) |
|
(? flags : x ) | 그룹 내의 |
\ n | 그룹을 역참조합니다.
|
\k< Name > | 명명된 그룹을 역참조합니다. |
수량자
수량자는 여러 번 반복되는 패턴을 찾기 위한 정규 표현식의 요소입니다.
정규 표현식의 수량자 | |
---|---|
x * |
|
x + |
|
x ? |
|
x ? |
|
x { n } |
|
x { n ,} |
|
x { n , m } |
|
수량자 옆에 ?
를 붙이면 수량자의 "탐욕적인" 특성을 지웁니다.
x
+
수량자를 예로 들겠습니다. /b+/
는 "aaabbbbbbbbbbcc" 문자열에 대해 모든 "b"가 이어져있는 "bbbbbbbbbb"와 일치합니다. 이는 패턴을 만족하는 최대한 긴 문자열을 찾으려는 특성, 즉 "탐욕적인" 특성 때문입니다.
하지만 ?
는 패턴을 만족하는 즉시 탐색을 중지합니다. /b+?/
는 "aaabbbbbbbbbbcc" 문자열에 대해 "b"와 일치합니다. /b+/
는 1개 이상의 "b"를 가리키는 패턴이므로 /b+?/
는 1개의 "b"를 찾은 즉시 탐색을 중단하기 때문입니다.
플래그
플래그(flag)는 정규 표현식의 탐색에 추가적인 옵션을 부여합니다.
정규 표현식의 플래그 | |
---|---|
d 메신저봇R 0.7.40-alpha.03 이상 | 일치 결과의 |
g | 패턴과 일치하는 모든 결과를 탐색합니다. |
i | 대소문자를 구분하지 않습니다. |
m | 여러 줄에 걸쳐 탐색합니다. 여러 줄의 문자열일 경우 줄바꿈을 기준으로 별개의 문자열로 나누어 탐색합니다. |
s | 줄바꿈 문자와 |
u 메신저봇R 0.7.40-alpha.03 이상 | 패턴을 유니코드 코드 포인트의 시퀀스로 간주합니다. |
y 메신저봇R 0.7.34a 이상 | 탐색 대상이 되는 문자열의 특정 위치에서 탐색을 시작합니다. |
플래그는 위와 같이 하나의 소문자 알파벳 형태를 가집니다. 플래그를 적용하는 방법은 아래와 같습니다.
new RegExp("\\d{2,6}", "g"); // g 플래그 적용 new RegExp("\\d{2,6}", "gim"); // g, i, m 플래그 적용 // 또는 /\d{2,6}/g; // g 플래그 적용 /\d{2,6}/gim; // g, i, m 플래그 적용
정규 표현식 사용하기
정규 표현식(RegExp
객체)은 문자열(String
객체)과 함께 사용하는 경우가 많습니다.
RegExp
객체의 메소드와 정규 표현식과 관련된 String
객체의 메소드를 익히면 정규 표현식을 더 잘 활용할 수 있습니다.
RegExp 객체의 메소드
RegExp 객체의 메소드 | |
---|---|
exec() | 인자로 전달된 문자열에서 정규 표현식의 패턴에 대한 일치 결과를 배열로 반환합니다. 일치하는 부분이 없는 경우
|
test() | 인자로 전달된 문자열이 정규 표현식의 패턴과 일치하는 부분이 존재하는지의 여부를 반환합니다.
|
String 객체의 유용한 메소드
정규 표현식과 관련된 String 객체의 메소드 | |
---|---|
match() | 문자열에서 인자로 전달된 정규 표현식의 패턴과 일치하는 부분을 배열 형태의 일치 결과로 반환합니다. 일치하는 부분이 없는 경우
|
search() | 문자열에서 인자로 전달된 패턴과 일치하는 위치(인덱스)를 반환합니다. 일치하는 부분이 없는 경우
|
replace() | 문자열의 특정 부분을 다른 문자열로 치환합니다. 인자로 문자열 뿐만 아니라 정규 표현식도 전달할 수 있습니다.
|
replaceAll() | 문자열의 모든 특정 부분을 다른 문자열로 치환합니다. 인자로 문자열 뿐만 아니라 정규 표현식도 전달할 수 있습니다. 정보 첫번째 인자에 정규 표현식을 사용할 때
|