Updated:

정규 표현식의 기본

정규 표현식

정규 표현식(regular expression)은 문자열의 패턴을 표현하기 위한 도구이다. 정규 표현식을 사용하면 문자열 안에서 특정 패턴을 가지는 문자열을 검색/추출/치환하는 등의 고급 문자열 처리 코드를 직접 작성하지 않고도 구현할 수 있다.

정규 표현식의 생성

자바스크립트의 정규 표현식은 RegExp 객체로 표현한다. 정규 표현식은 RegRxp 생성자 또는 정규 표현식 리터럴로 생성할 수 있다.

var reg = new RegExp("abc");  // RegExp 생성자로 생성
var reg = /abc/;  // 정규 표현식 리터럴로 생성

이 두 개의 정규 표현식은 똑같은 정규 표현식 객체를 생성한다. 위의 코드는 모두 ‘“abc”라는 문자열을 포함한다’라는 뜻을 가진 문자열의 패턴을 표현한 것이다. 이 “abc” 부분을 정규 표현식 패턴이라고 한다. 정규 표현식 패턴을 작성할 때는 숫자(0~9)와 알파벳(a~z,A~Z) 등의 일반 문자와 ‘+’,’.’등의 특수문자를 사용한다. 정규 표현식에서 사용하는 특수문자는 메타 문자(meta character)라고 하며, 이 메타 문자를 문자로서 사용할 때는 앞에\문자를 붙여 주어야 한다.

패턴 매칭

어떤 문자열이 정규 표현식이 표현하는 문자열의 패턴을 가지고 있을 때 그 문자열을 가리켜 정규 표현식과 일치(Match)한다고 한다. 문자열이 정규 표현식과 일치하는지 확인하는 작업을 가리켜 패턴 매칭이라고 한다.

RegExp 객체의 메서드

자바스크립트 정규 표현식을 사용하여 문자열을 처리하려면 RegExp.prototype의 test, exec 매서드를 사용하거나 String.prototype의 match, replace, search, split 매서드를 사용한다. 이 정레서는 RegExp.prototype의 test와 exec 메서드의 간단한 사용법을 알아본다.
test 메서드는 정규 표현식 문자열이 일치하는지 뜻하는 논리값을 반환한다.

var reg = /cat/;
console.log(reg.test("cats and dogs")); // true
console.log(reg.test("Cat"));           // false

exec 메서드는 정규 표현식과 일치하는 문자열을 검색하여 일치한 문자열을 배열로 반환한다. 일치하는 문자열을 찾지 못했을 때는 null을 반환한다.

var reg = /Script/;
var result = reg.exec("JavaScript");
console.log(result[0]); // Script

반환된 배열에는 index와 input 프로퍼티가 있다. index 프로퍼티에는 가장 처음 일치한 위치가 들어가고 input 프로퍼티에는 일치한 문자열이 들어간다.

console.log(result.index);  // 4
console.log(result.input);  // "JavaScript"

기본적인 정규 표현식 패턴 작성하기

이제부터 메타 문자를 사용한 기본적인 정규 표현식 패턴 작성법을 소개한다.

리터럴 문자

정규 표현식의 패턴이 일반 문자와 메타 문자로 구성되는데 이때 일반 문자는 리터럴 문자라고 한다. 리터럴 문자는 유티코드 문자, \n, \t 들이 있다.
다음 문자는 정규 표현식에서 특별한 뜻을 갖는 메타 문자(정규 표현식의 구문 문자)이다.
` ^ $ \ . * + ? ( ) [ ] { } | `

문자 클래스

문자 클래스:[…]
문자 클래스는 특정 문자 집합 안의 모든 단일 문자와 일치한다. 문자 클래스를 정의하려면 문자 집합의 요소가 되는 문자 리터럴을 나열하여 대괄호로 묶어 준다.

[abc]       // 'a', 'b', 'c' 중 문자 한개와 일치
[a-z]       // 전체 소문자 중 문자 한 개
[a-zA-Z0-9] // 모든 알파벳과 숫자 중 문자 한 개

부정 문자 클래스:[^…]
[^…]는 문자 클래스인 대괄호 안에 들어 있지 않은 단일 문자와 일치한다.

[^0-9]  // 숫자 이외 문자 한개와 일치

문자 클래스의 단축 표기

자주 사용되는 문자 클래스에는 다음과 같은 단축 표기법이 있다.

임의의 문자 한개 : .
마침표(.)는 줄 바꿈 문자를 제외한 임의의 문자 한 개와 일치한다.
숫자와 숫자 외의 문자 : \d, \D
\d는 숫자로 해석할 수 있는 문자 한 개와 일치한다. \d는 [0123456789]의 단축 표기이다. \D는 [^0123456789]의 단축 표기이다.
단어 문자와 단어 문자 외의 문자 : \w, \W
\w는 모든 영어 단어 문자(알파벳, 숫자, 언더스코어)라는 뜻이다. 즉 \w는 [a-zA-A0-9_]의 단축 표기이다. \W는 영어 단어 문자가 아닌 문자와 일치한다.
공백 문자와 공백 문자 외의 문자 : \s, \S
\s는 모든 공백 문자(공백 문자, 탭 문자, 개행 문자 등)와 일치한다. \S는 공백 문자가 아닌 문자와 일치한다.
문자 클래스 안에서의 이스케이프
\ 문자가 붙어 있는 단축 표기는 대괄호 안에 문자 클래스를 작성할 떄도 같은 뜻으로 사용할 수 있다. 예를 들어 [\s\w]는 공백 문자 한 개 또는 영어 단어 문자 중 한 개와 일치한다. 메타 문자를 문자 클래스 안에서 사용하면 메타 문자로서의 특별한 의미를 잃고 그 문자 자체를 뜻하게 된다.

반복 패턴

반복 패턴을 사용하면 정규 표현식의 요소를 여러번 반복하도록 지정하여 더욱 간결하게 표기할 수 있다.

최소 m번, 최대 n번 반복 : {m, n}

/[a-z]{6,12}/   // 알파벳 소문자가 여섯 자 이상이며 열두 자 이하인 문자열과 일치

바로 앞의 요소를 최소 n번 반복 : {n,}
바로 앞의 요소를 n번 반복 : {n}
최대 한 번 반복 : ?
최소 한 번 반복 : +
최소 0번 반복 : *
욕심 없는 반복 : 반복 문자 ?

그룹화와 참조

그룹화 : (…)
정규 표현식의 패턴 요소를 소괄호로 묶으면 부분적으로 그룹화할 수 있다. 그룹화한 부분은 ?, +, * 등을 사용해서 반복할 수도 있고, |을 사용해서 선택의 범위를 좁힐 수도 있다. 그룹화 된 부분(소괄호로 묶은 부분)은 부분 정규 표현식이 된다. 이 부분 정규 표현식과 일치한 값은 별도로 저장되므로 나중에 그 부분을 다시 참조할 구도 있고 이렇게 일차한 값을 저장하는 동작을 가리켜 캡처링(저장)이라고 한다.
캡처링 없는 그룹화 : (?:…)
캡처링 없는 그룹화도 할 수 있다.

위치를 기준으로 매치하기

문자열의 위치를 패턴으로 지정하는 앵커라는문자가 있다.
문자열의 시작 위치 : ^
^은 문자열의 시작 위치에 패턴을 고정한다.
문자열의 마지막 위치 : $
$는 문자열의 마직막 위치에 패턴을 고정한다.
영어 단어의 경계: \b
/b는 영어 단어의 경계 위치화 일치한다. \b는 영어 문자의 시작 부분 또는 끝부분의 다른 문자가 없는 위치에 매칭한다.
영어 단어 외의 위치 : \B
/B는 영어 단어 경계 외의 위치에 일치한다.
전방 탐색 : (?=pattern)
x(?=y)라고 표기하면 x 다음에 y가 나오는 패턴이 된다.
전방 부정 탐색 : (?|pattern)
x(?|y)라고 표기하면 x다음에 y가 나오지 않는 패턴이 된다.

선택 패턴

선택 패턴은 문자열 여려 개 중에서 문자열 하나와 일치한다. 선택 패턴을 정의할 때는 후보가 되는 패턴 문자열을 |로 연결해서 표기한다.

플래그

정규 표현식에는 고급 검색을 설정하기 위한 플래그가 다섯 개 있다. 이들 플래그는 한 개만 성정할 수도 있도 여러 개를 조합해서 설정할 수도 있다.

플래그
i 대문자와 소문자를 구별하지 않는다.
g 전역 검색한다. 처음뿐만 아니라 일치하는 모든 것을 검색한다.
m 여러 줄 모드로 검색한다. 앵커 문자^과 $는 각각 행이 시작과 끝이라는 뜻이다.
y 시작 위치 고정 검색을 한다.
u 정규 표현식 패턴을 내부적으로 유니코드 코드 포인트 열로 처리한다.

플래그를 설정하는 방법

정규 표현식을 RegExp 생성자로 생성할 때 플레그를 성정하려면 두 번째 인수에 플레그를 문자열로 넘긴다. 정규 표현식을 정규 표현식 리터럴로 생성할 때 를레그를 설정하려면 마지막 / 문자 뒤에 플레그를 붙여 주고 플래그 여러개를 동시에 설정하려면 플래그 문자를 나열한 문자열을 붙여준다.

var reg1 = new RegExp("abc","g");
var reg2 = /abc/g;
var reg3 = /abc/gi;

패턴 매칭을 하는 문자열 메서드

이 절에서는 String 객체의 메서드와 정규 표현식을 함께 사용하는 방법을 배운다.

문자열 검색하기 : search 메서드

search 메서드는 인수로 받은 정규 표현식 객체와 일치한 최초 문자열의 첫 번째 문자 위치를 반환하고 일치하는 문자를 찾기 못했을 때는 -1을 반환한다. search 메서드는 원본 문자열을 수정하지 않는다. search 메서드는 전역 검색을 지원하지 않으므로 g플레그를 성정해도 무시한다.

var s = "1 little,2 little indian";
console.log(s.search(/little/));    // 2 : 일치한 최초 문자열의 첫 번째 문자 위치
console.log(s.search(/\d/));        // 0 : 일치한 최초 문자열의 첫 번째 문자 위치
console.log(s.search(/\bindian/));  // 18 : 일치한 i의 위치
console.log(s.search(/3\s/));       // -1 : 일치하지 않음

문자열 치환하기 : replace 메서드

replace 메서드의 기본적인 사용법
replace 메서드는 첫 번째 인수로 받은 정규 표현식과 일치하는 문자열을 검색하고, 두 번째 인수로 받은 문자열로 치환한 새로운 문자열을 반환한다. replace 메서드는 원본 문자열을 고치지 않는다. 정규 표현식에 g 플레그를 설정하면 일치한 문자열을 모두 치환한다. g 플레그를 설정하지 않으면 가장 처음 일치한 문자열만 치환한다.

var s = "1 little,2 little indian";
console.log(s.replace(/indian/,"boy")); // 1 little,2 little boy
console.log(s.replace(/little/,"big")); // 1 big,2 little indian
console.log(s.replace(/little/g,"big")); // 1 big,2 big indian

치환 패턴 : $n, $&
두 번째 인수인 대체 문자열에는 특수한 치환 패턴인 $n, $&을 사용할 수 있다.
①$n에는 정규 표현식 안에 소괄호를 사용하여 그룹화한 n번째 부분 정규 표현식과 일치한 문자열이 들어가며, n에는 0~9999 사이의 값을 넣을 수 있다.

var person = "Tom, tom@example.com, 010-1234-5678";
var date = "오늘은 2016년9월10일 입니다.";
var name = "Tom Sawyer";
var result1 = person.replcae(/0(\d{1,4}-\d{1,4}-\d{4})/g),"+82-$1");
var result2 = date.replace(/(\d+)(\d+)(\d+)일/,"$1/$2/$3");
var result3 = name.replace(/(\w+)\s(\w+)/,"$2 $1");
console.log(result1); // Tom, tom@example.com, +82-10-1234-5678
console.log(result2); // 오늘은 2016/9/10 입니다.
console.log(result3); // Sawyer Tom

②$&에는 일치한 부분 문자열이 들어온다.

var address = "121-842 서울특별시 마포구 월드컵로10길 56";
var result = address.replace(/\d{3}-\d{3}/,"ⓐ$&");
console.log(result);  // ⓐ121-842 서울특별시 마포구 월드컵로10길 56

문자열 치환을 처리하는 함수
두 번째 인수에함수를 넘길 수도 있다.

함수
match 일차한 부분 문자열($&과 같은 값)
groupn n 번째 부분 정규 표현식과 일치한 부분 문자열($n과 같은 값)
offset 일치한 부분 문자열의 첫 번째 문자 위치
inputStr 원본 문자열 전체

문자열 추출하기 : match 메서드

match 메서드는 첫 번째 인수로 받은 정규 표현식과 일치하는 문자열을 순서대로 저장해서 배열로 반환한다. 정규 표현식에 g 플레그를 설정하지 않으면 가장 처음 일치한 문자열만 반환한다.

"1 little,2 little indian".match(/\d+/g); // ["1", "2"]

문자열 나누기 : split 메서드

split 메서드의 기본적인 사용법
split 메서드는 첫 번째 인수로 문자열을 분할한 다음에 배열에 담아서 반환한다. 첫 번째 인수로는 문자열 또는 정규 표현식 객체를 넘긴다. 첫 번째 인수를 생략하면 원본 문자열 전체를 배열에 담아서 반환한다.

console.log("172.20.51.65".split(".")); // ["127", "20", "51", "65"]

반환할 문자열의 개수 제한하기
split 메서드의 두 번째 인수는 선택 사항이다. 두 번쨰 인수로는 반환할 문자열의 개수를 제한할 수 있다.

console.log("1, 2, 3, 4, 5".split(/\s*,\s*/,3));  // ["1", "2", "3"]

RegExp 객체

이 절에서는 RegExp 객체의 프로퍼티와 메서드를 사용해서 문자열을 처리하는 방법을 배운다.

RegExp 객체의 프로퍼티

RegExp 객체는 RegExp.prototype에서 프로퍼티와 메서드를 상속받는다.

프로퍼티 설명
source 정규 표현식 패턴 문자열을 저장한다.
global g 플레그가 사용되고 있는지를 뜻하는 논리값. 읽기 전용
ignoreCase i 플레그가 사용되고 있는지를 뜻하는 논리값. 읽기 전용
multiline m 플레그가 사용되고 있는지를 뜻하는 논리값. 읽기 전용

RegExp의 메서드

RegExp는 test와 exec 두 개의 메서드를 가지고 있다.
exec 메서드의 반환값
exec 메서드는 정규 표현식과 일치하는 문자열을 검색해서 일치한 문자열과 부분 정규 표현식에 일치한 문자열을 배열에 담아 반환한다. 일치하는 문자열을 찾지 못했을 때는 null을 반환한다.
lastIndex 프로퍼티
g 플래그를 설정한 정규 표현식으로 exec나 test 메서드를 실행하면 일치한 문자열 바로 다음 번 문자의 위치가 정규 표현식 객체의 lastIndex 프로퍼티에 저장된다. 일치하지 않을 때는 0이 저장된다. 같은 정규 표현식 객테로 다시 한 번 exec나 test메서드를 호출하면 lastIndex 프로퍼티가 가리키는 문자의 위치에서 검색을 재개한다.

var tel = /(\d{2,5})-(\d{1,4})-(\d{4})/g;
var test = "Tom: 010-1234-5678\nHuck: 020-550-7809\nBecky: 030-4321-9876";
console.log(tel.lastIndex);   // 0
console.log(tel.exec(test));  // ["010-1234-5678", "010", "1234", "5678"]
console.log(tel.lastIndex);   // 18
console.log(tel.exec(test));  // ["020-550-7809", "020", "550", "7809"]

g 플래그를 설정한 정규 표현식 객체의 exec 메서드를 계속 호출하면 일치한 문자열을 순서대로 구할 수 있다. 이 성질을 활용하면 exec 메서드를 반복 호출해서 정규 표현식과 일치한 문자열의 모든 매칭 정보를 구할 수 있다. 정규 표현식이 반환한 값 안의 lastIndex 프로퍼티는 수정할 수 있다. 따아서 값을 설정해서 원하는 문자의 위치에서 검색을 시작할 수 있다.

ECMAScript 6부터 추가된 정규 표현식의 새로운 기능

u 플래그 —— ECMAScript 6부터 추가된 u 플래그를 설정하면 문자열을 유니코드 코드 포인트 열로 처리한다.

y 플래그

y 플래그를 설정하면 시작 위치 고정 검색을 할 수 있다. 이를 활용하면 정규 표현식 객체의 lastIndex 프로퍼티의 인덱스가 가리키는 그 위치부터 검색을 시작할 수 있다.

flags 프로퍼티

ECMAScipt 6부터는 flags 프로퍼티로 플래그 문자열을 쉽게 확인할 수 있다.

RegExp의 인수로 정규 표현식을 넘겼을 때의 동작

RegExp 생성자의 첫 번째 인수로 정규 표현식 객체를 넘기면 객체와 같은 패턴을 지닌 정규 표현식 객체가 생성된다. ECMAScipt 6부터는 두 번째 인수로 플래그를 넘겨서 원본 정규 표현식 객체와는 다른 플래그를 사용하도록 할 수 있다.

댓글남기기