정규 표현식

Doum Kim·2020년 5월 10일
0

정규 표현식

정규 표현식이란?

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

정규 표현식은 원래 유닉스의 스크립트 언어 처리에서 사용되던 표기법이다. 현재는 Perl, java, Javascript 등의 프로그래밍 언어에 내장되어있다.

자바 스크립트에서 정규 표현식

정규 표현식의 생성

자바 스크립트에서 정규 표현식은 RegExp 객체 또는 정규 표현식 리터럴로 생성가능하다.

const reg1 = new RegExp('abc');
const reg2 = /abc/;

위의 코드는 abc라는 문자열을 포함한다라는 뜻을 가진 문자열의 패턴을 표현한 것이다.
'abc' 부분을 정규 표현식 패턴이라고 한다. 정규 표현식에서 사용하는 특수문자는 메타 문자라고 하며, 이 메타 문자를 문자로 사용할 때는 \를 붙여 사용한다.

패턴 매칭

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

const reg = /abc/;

"abc" // 일치
"ccc" // 불일치
"abcdef" // 일치

RegExp 객체의 메서드

자바스크립트로 정규 표현식을 사용하여 문자열 처리를 하려면 RegExp.prototype의 test, exec 메서드를 사용하거나 String.prototype의 match, replace, search, split 메서드를 사용한다.

test

test 메서드는 정규 표현식 문자열이 일치하는지 뜻하는 논리값을 반환한다.

const reg = /abc/;
console.log(reg.test("abc ddd eee");  //true
console.log(reg.test("add eee ccc"); //false

exec

exec 메서드는 정규 표현식과 일치하는 문자열을 검색하여 일치한 문자열을 배열로 반환한다. 반환된 배열에는 index, input 프로퍼티가 있다. index는 가장 처음 일치한 위치, input에는 일치한 문자열이 들어간다.

const reg = /monday/;
const result = reg.exec('Today is monday!!');

console.log(result); //["monday"]
console.log(result[0]); //monday
console.log(result.index); // 9
console.log(result.input); // Today is monday!! 

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

정규 표현식의 핵심은 메타 문자를 사용한 문자열 패턴의 표현이다. 이를 활용하여 다양한 유형의 문자열 패턴을 표현할 수 있다. 또한 정규 표현식 패턴의 규칙은 같은 문자라도 위치에 따라 메타 문자로 해석할 수도 있고 리터럴로 해석할 수 있기 때문에 매우 복잡하다.

리터럴 문자

정규 표현식의 패턴은 일반 문자와 메타 문자로 구성된다. 여기서 일반 문자는 리터럴 문자라고 한다.

table.aligncenter{display:block; margin:0 auto}

리터럴 문자설명
유니코드문자문자 그 자체를 뜻한다.
\0NULL 문자
\n개행 문자
\t탭 문자
\v수직 탭 문자
\f다음 페이지 문자
\r캐리지 리턴 문자
\xhh16진수 hh로 지정된 ASC 문자
uhhhh16진수 hhhh로 지정된 유니코드 문자
cX제어 문자

정규표현식에서 특별한 뜻을 갖는 메타 문자는 아래와 같다.

^ $ . + ? () [] {} |

이러한 메타 문자를 표기할 때는 메타 문자 앞에 \를 붙여서 이스케이프한다.

RegExp 객체로 정규표현식을 생성할 때 \ 문자를 다루는 법

const reg = /\d+/;  // 리터럴으로 생성
const reg2 = new RegExp("\\d+"); // RegExp 객체로 생성  -> \d+ 패턴

이처럼 RegExp로 생성하는 방법이 까다로워 대부분 정규 표현식 리터럴을 사용하는 것이 좋다. 단, 정규 표현식 패턴을 동적으로 설정하려면 RegExp 생성자를 사용해야만 한다.

문자 클래스

문자 클래스는 특정 문자 집합 안의 모든 단일 문자와 일치한다.
문자 클래스인 대괄호 안에서 하이픈(-)을 사용하면 문자의 범위를 지정할 수 있다.
-문자는 그 앞뒤 문자가 모두 리터럴 문자일 때만 범위라는 뜻을 갖는다.

const reg = /[abcd]/;
const result1 = reg.test("ad"); 
const result2 = reg.test("f f f"); 

console.log(result1); // true
console.log(result2); //false

const reg2 = /[a-c]/;
const result3 = reg2.test("C is c");
const result4 = reg2.test("D is d");

console.log(result3); //true
console.log(result4); //false
문자 클래스패턴
[a-z]전체 소문자 알파벳 중 문자 하나
[abcx-z]a,b,c,x,y,z 중 문자 하나
[a-zA-Z0-9]모든 알파벳과 0-9 숫자 중 문자 하나
[\u3131-\u314E]한글 자음 한개
/<h[1-6]>/h1 - h6 태그

부정 문자 클래스

부정 문자 클래스 [^...]는 문자 클래스인 대괄호 안에 들어 있지 않은 단일 문자와 일치한다. []안의 패턴이 ^으로 시작하지 않으면 ^를 문자로 인식한다.

const reg = /[^abcd]/;
const result1 = reg.test("ad"); 
const result2 = reg.test("f f f"); 

console.log(result1);//false
console.log(result2);// true

문자 클래스의 단축 표기

단축 표기를 활용하여 문자 클래스를 더욱 간결하게 표기할 수 있다.

.

마침표(.)는 줄 바꿈 문자를 제외한 임의의 문자 한 개와 일치한다.

\d, \D

\d는 숫자로 해석할 수 있는 문자 한 개와 일치한다. \d는 [0123456789]의 단축 표기법이다.

\D는 [^0123456789]의 단축 표기법이다.

\w, \W

\w는 모든 영어 단어문자(알파벳, 숫자, 언더스코어)라는 뜻이다. [a-zA-Z0-9_]의 단축 표기법이다.

\W는 [^a-zA-Z0-9_]의 단축 표기법이다.

\s, \S

\s는 모든 공백 문자(공백문자, 탭문자, 개행문자 등)와 일치한다.

\S는 모든 공백 문자가 아닌 문자와 일치한다.

문자 클래스 안에서의 이스케이프

문자 클래스 안에서 메타문자를 사용하면 특별한 의미를 잃고 그 문자 자체를 뜻한다.
단, ], \, - 의 메타 문자를 사용할 경우 \ 문자를 앞에 붙여서 이스케이프해야 한다.

const reg1 = /a./;
console.log(reg1.test("a")); //false
console.log(reg1.test("ab")); // true

const reg2 = /\d/;
console.log(reg2.test("0123")); //true
console.log(reg2.test("abc")); //false

const reg3 = /\w/;
console.log(reg3.test("asdf")); //true
console.log(reg3.test("@*&#^")); //false

const reg4 = /\s/;
console.log(reg4.test("abcd efg")); //true
console.log(reg4.test("abcdefg")); //false

const reg5 = /[[\]]/;
console.log(reg5.test("[")); //true
console.log(reg5.test("]")); //true

반복 패턴

패턴을 작성할 때 반복 패턴을 이용해 정규 표현식의 요소를 여러번 반복하도록 지정하여 간결하게 표기할 수 있다.

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

{m,n}는 바로 앞의 요소를 최소 m번, 최대 n번 반복한다.

바로 앞의 요소를 최소 n번 반복 : {n,}

{n,}는 바로 앞의 요소를 최소 n번 이상 반복한다.

바로 앞의 요소를 n번 반복 : {n}

{n}는 바로 앞의 요소를 n번 반복한다. (={n,n})

최대 한 번 반복 : ?

?는 바로 앞의 요소를 최소 0번 최대 한 번 반복한다. (={0,1})

최소 한 번 반복 : +

+는 바로 앞의 요소를 최소 한 번 이상 반복한다. (={1,})

최소 0번 반복 : *

+는 바로 앞의 요소를 최소 0번 이상 반복한다. (={0,})

const reg1 = /[a-z]{6,12}/;
console.log(reg1.test("abcdefgh")); //true
console.log(reg1.test("abcde")); //false

const reg2 = /[a-z]{3,}/;
console.log(reg2.test("abcd")); //true
console.log(reg2.test("ab")); //false

const reg3 = /[a-z]{4}\d{3}/;
console.log(reg3.test("abcd123")); //true
console.log(reg3.test("abcd12")); //false

const reg4 = /[a-z]{4}\d?/;
console.log(reg4.test("abcd")); //true
console.log(reg4.test("abcd1")); //true

const reg5 = /\s+Tom\s+/;
console.log(reg5.test("Hello Tom ?")); //true

const reg6 = /[a-z]{4}\d*/;
console.log(reg6.test("abcd")); //true
console.log(reg6.test("abcd1234")); //true

욕심 없는 반복 : 반복문자 ?

.*는 가능한 최대 횟수만큼 반복해서 일치한 결과를 반환한다. 이러한 반복을 '욕심 많은 반복'이라 한다.

console.log(/Java.*/.exec("I love JavaScript")); // ["JavaScript"]

반대로 최소한으로 반복하는 '욕심 없는 반복'을 지정할 수도 있다.

console.log(/Java.*?/.exec("I love JavaScript")); // ["Java"]

console.log(/0*?1/.exec('000012')); //  ["00001"]

그룹화와 참조

그룹화

정규표현식의 패턴 요소를 소괄호로 묶으면 부분적으로 그룹화가 가능하다. 그룹화한 부분은 반복 등의 작업을 할 수 있다.

그룹화된 부분은 부분 정규 표현식이 된다. 이 부분 정규 표현식과 일치한 값을 별도로 저장되며 나중에 그 부분을 다시 참조할 수 있다. 이렇게 일치한 값을 저장하는 동작을 캡처링(저장)이라고 한다.

const reg = /<h[1-6]>.*<\/h[1-6]>/;
console.log(reg.test("<h1>Hello world!</h1>")); //true
console.log(reg.test("<h1>Hello world!</h2>")); //true

const reg2 = /<(h[1-6])>.*<\/\1>/;
console.log(reg2.test("<h1>Hello world!</h1>")); //true
console.log(reg2.test("<h2>Hello world!</h1>")); //false
console.log(reg2.test("<h2>Hello world!</h2>")); //true

console.log(reg2.exec("<h2>Hello world!</h2>")); // ["<h2>Hello world!</h2>", "h2"]

exec 메서드가 반환하는 배열의 첫 번째 요소는 정규 표현식과 일치한 마지막 문자열이 들어가고, 그 이후 요소에는 각 부분 정규 표현식과 일치한 문자열이 하나씩 들어간다.

캡처링 없는 그룹화 : (?:...)

그룹화를 (?:...) 식으로 하면 캡처링이 없는 그룹화가 가능하다.

const reg3 = /(?:h[1-6]).*<\/\1>/;
console.log(reg3.test("<h1>Hello world!</h1>")); //false
console.log(reg3.exec("<h1>Hello world!</h1>")); //null

위치를 기준으로 매칭하기

문자열의 시작 위치 : ^, 마지막 위치 : $

^은 문자열의 시작 위치에 패턴을 고정한다. 반대로 $는 문자열의 마지막 위치에 패턴을 고정한다. /^문자열$/의 패턴을 이용하면 문자열의 내용만 포함하는 문자열을 검색한다.

const first = /^Kim/;
console.log(first.test("Kim is man")); //true
console.log(first.test("My name is Kim")); //false

const last = /Kim$/;
console.log(last.test("Kim is man")); //false
console.log(last.test("My name is Kim")); //true

const onlyKim = /^Kim$/;
console.log(onlyKim.test('Kim is man')) //false
console.log(onlyKim.test('Kim')) //true

영어 단어의 경계 : \b

const dog = /\bdog\b/;
console.log(dog.test("I love dog.")); // true
console.log(dog.test("My favorite dog is...")); //true
console.log(dog.test("dog is...")); //true

전방 탐색 : (?=pattern), (?!pattern)

console.log(/java(?=Script)/.exec("javaScript")); //["java"]
console.log(/java(?=Script)/.exec("javascript")); //null

console.log(/java(?!Script)/.exec("javaScript")); //null
console.log(/java(?!Script)/.exec("javascript")); //["java"]

선택 패턴

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

const animal = /dog|cat|turtle/;

console.log(animal.test('123 dog')); //true
console.log(animal.test('123 cat')); //true
console.log(animal.test('123 turtle')); //true

플래그

정규 표현식에는 고급 검색을 설정하기 위한 플래그 5가지가 있다. 플래그는 한가지만 설정할 수도 있고 여러 개를 복합적으로도 설정 가능하다.

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

플래그 설정 방법

/**RegExp 생성자로 생성 (두 번째 인수에 플래그를 문자열로 넘김)**/
const reg = new RegExp('abc','g');

/**리터럴로 생성 (마지막 / 문자 뒤에 플래그를 붙여준다.)**/
const reg2 = /abc/g;
const reg3 = /abc/gi; //여러 개의 플래그 사용

참고
regexr,
Regexper

0개의 댓글