[모던 자바스크립트] RegExp

재오·2023년 7월 28일
5

JavaScript

목록 보기
42/48
post-thumbnail

정규 표현식은 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어다. 정규 표현식은 문자열을 대상으로 패턴 매칭 기능 을 제공한다. 패턴 매칭 기능이란 특정 패턴과 일치하는 문자열을 검색하거나 추출 또는 치환할 수 있는 기능을 말한다.

예를 들어, 휴대폰 전화번호가 유요한 휴대폰 전화번호인지 체크하는 경우를 생각해 보자.

const tel = '010-1234-5678';

const regExp = /^\d{3}-\d{4}-\d{4}$/;
regExp.test(tel); // true

만약 정규 표현식을 사용하지 않는다면 반복문과 조건문을 통해 한 문자씩 연속해서 체크해야 한다. 하지만 정규 표현식을 사용하면 반복문과 조건문 없이 패턴을 정의하고 테스트하는 것으로 간단히 체크할 수 있다. 하지만 가독성이 좋지 않다는 문제가 있다.

정규 표현식의 생성

정규 표현식 객체를 생성하기 위해서는 정규 표현식 리터럴 을 사용하는 것이 좋다.

정규 표현식 리터럴은 패턴과 플래그로 구성된다.

const target = 'Is this all there is?';
const regexp = /is/i;

regexp.test(target); // true

RegExp 생성자 함수를 사용하면 변수를 사용해 동적으로 RegExp 객체를 생성할 수 있다.

const count = (str, char) => (str.match(new RegExp(char, 'gi')) ?? []).length;
                              
count('Is this all there is?', 'is'); // 3
count('Is this all there is?', 'xx'); // 0

RegExp 메서드

RegExp.exec
exec 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 배열로 반환한다. 매칭 결과가 없는 경우 null을 반환한다. exec 메서드는 문자열 내의 모든 패턴을 검색하는 g 플래그를 지정해도 첫 번째 매칭 결과만 반환하므로 주의해야 한다.

const target = 'Is this all there is?';
const regExp = /is/;

regExp.exec(target); // ["is", index:5, input: "Is this al there is?", groups: undefined]

RegExp.test
test 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환한다.

const target = 'Is this all there is?';
const regExp = /is/;

regExp.test(target); // true

RegExp.match
match 메서드는 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭 결과를 배열로 반환한다.

const target = 'Is this all there is?';
const regExp = /is/;

target.match(regExp); // ["is", index:5, input: "Is this al there is?", groups: undefined]

exec 메서드는 문자열 내의 모든 패턴을 검색하는 g 플래그를 지정해도 첫 번째 매칭 결과만 반환한다. 하지만 match 메서드는 g 플래그가 지정되면 모든 매칭 결과를 배열로 반환한다.

const target = 'Is this all there is?';
const regExp = /is/g;

target.match(regExp); // ["is", "is"];

플래그

패턴과 함께 정규 표현식을 구성하는 플래그는 정규 표현식의 검색 방식을 설정하기 위해 사용한다. 플래그는 총 6개 있다. 그중 중요한 3개의 플래그는 아래와 같다.
i: 대소문자를 구별하지 않고 패턴을 검색한다.
g: 대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색한다.
m: 문자열의 행이 바뀌더라도 패턴 검색을 계속한다.

어떠한 플래그를 사용하지 않은 경우 대소문자를 구별해서 패턴을 검색한다. 그리고 문자열에 패턴 검색 매칭 대상이 1개 이상 존재해도 첫 번째 매칭한 대상만 검색하고 종료한다.

const target = 'Is this all there is?';

target.match(/is/); // index: 5

target.match(/is/i); // index: 0

target.match(/is/g); // ["is", "is"]

target.match(/is/ig); // ["Is", "is", "is"]

패턴

정규 표현식은 패턴과 플래그로 구성된다. 정규 표현식의 패턴은 문자열의 일정한 규칙을 표현하기 위해 사용하며, 정규 표현식의 플래그는 정규 표현식의 검색 방식을 설정하기 위해 사용한다.

패턴은 /로 열고 닫으며 문자열의 따옴표는 생략한다. 어떤 문자열 내에 패턴과 일치하는 문자열이 존재할 때 '정규 표현식과 매치한다'고 표현한다. 패턴을 표현하는 몇 가지 방법에 대해 살펴보자.

문자열 검색
검색 대상 문자열과 플래그를 생략한 정규 표현식의 매칭 결과를 구하면 대소문자를 구별하여 정규 표현식과 매치한 첫 번째 결과만 반환한다.

앞에서 봤던 예시는 모두 문자열 검색에 해당하므로 skip한다.

임의의 문자열 검색
. 은 임의의 문자 한 개를 의미한다. 문자의 내용은 무엇이든 상관없다.

const target = 'Is this all there is?';

const regExp = /.../g;

target.match(regExp); // "Is ", "thi", "s a", "ll ", "the" ...

반복 검색
{m,n}은 앞선 패턴이 최소 m번, 최대 n번 반복되는 문자열을 의미한다. 콤마 뒤에 공백이 있으면 정상 동작하지 않으므로 주의해야 한다. {n}은 앞선 패턴이 n번 반복되는 문자열을 의미한다. {n,}은 앞선 패턴이 최소 n번 이상 반복되는 문자열을 의미한다.

const target = 'A AA B BB Aa Bb AAA';

const regExp = /A{1,2}/g;
const regExp2 = /A{2,}/g;

target.match(regExp); // "A" "AA" "A" "AA" "A"
target.match(regExp2); // "AA" "AAA"

+는 앞선 패턴이 최소 한번 이상 반복되는 문자열을 의미한다. 즉, +는 {1,}과 같다.

const target = 'A AA B BB Aa Bb AAA';

cosnt regExp = /A+/g;

target.match(regExp); // "A" "AA" "A" "AAA"

?는 앞선 패턴이 최대 한번이상 반복되는 문자열을 의미한다. 즉, ?는 {0,1}과 같다. 아래 예제는 'colo' 다음 'u'가 최대 한번 이상 반복되고 'r'이 이어지는 문자를 검색하는 것을 의미한다.

const target = 'color colour';

const regExp = /colou?r/g;

terget.match(regExp); // "color" "colour"

OR 검색
|는 OR의 의미를 갖는다.

const target = 'A AA B BB Aa Bb AAA';

cosnt regExp = /A|B/g;

target.match(regExp); // "A" "A" "A" "B" "B" "B" "A" "B"

아래 예제는 패턴을 or로 한 번 이상 반복하는 것인데 뒤에 +를 사용하면 앞선 패턴을 한 번 이상 반복한다.

const target = 'A AA B BB Aa Bb';

const regExp = /A+|B+/g;

target.match(regExp); // "A" "AA" "B" "BB" "A" "B"

위와 같이 OR을 대신해서 사용되는 방법이 대괄호 내에 문자를 적는 것이다.

const target = 'A AA B BB Aa Bb';

const regExp = /[AB]+/g;

target.match(regExp); // "A" "AA" "B" "BB" "A" "B"

범위를 지정하기 위해서는 [] 내에 -를 사용하면 된다. 다음 예제의 경우 대문자 알파벳을 검색한다.

const target = 'A AA BB ZZ Aa Bb';

const regExp = /[A-Z]+/g;

target.match(regExp); "A" "AA" "BB" "ZZ" "A" "B"

대소문자를 구별하지 않고 알파벳을 검색하는 방법은 다음과 같다.

const target = "AA BB Aa Bb 12";

const regExp = /[A-Za-z]+/g;

target.match(regExp); // "AA" "BB" "Aa" "Bb"

숫자를 검색하는 방법은 다음과 같다.

const target = "AA BB 12,345";

const regExp = /[0-9]+/g;

terget.match(regExp); // "12" "345"

위 예제의 경우 쉼표 때문에 매칭 결과가 분리되므로 쉼표를 패턴에 포함시킨다.

const target = "AA BB 12,345";

const regExp = /[0-9,]+/g;

terget.match(regExp); // "12,345"

위 예제를 간단히 표현하면 다음과 같다. \d 는 숫자를 의미한다. \d는 [0-9]와 같다. 반대로 \D 는 숫자가 아닌 문자를 의미한다.

const target = 'AA BB 12,345';

let regExp = /[\d,]+/g;

target.match(regExp); // "12,345"

regExp = /[\D,]+/g;

target.match(regExp); // "AA BB " ","

\w 는 알파벳, 숫자, 언더스코어를 의미한다. 즉, \w는 [A-Za-z0-9_] 와 같다. \W 는 그와 반대로 동작한다. 즉 알파벳, 숫자, 언더스코어가 아닌 문자를 의미한다.

const target = 'Aa Bb 12,345 _$%&';

let regExp = /[\w,]+/g;

NOT 검색
[...] 내의 ^ 은 NOT의 의미를 갖는다.

const target = 'AA BB 12 Aa Bb';

const regExp = /[^0-9]+/g;

target.match(regExp); // "AA BB " "Aa Bb"

시작 위치로 검색
[...] 밖의 ^ 은 문자열의 시작을 의미한다.

const target = 'https://poiemaweb.com';

const regExp = /^https/;

regExp.test(target); // true

마지막 위치로 검색
$는 문자열의 마지막을 의미한다.

const target = 'https://poiemaweb.com';

const regExp = /com$/;

regExp.test(target); // true

자주 사용하는 정규표현식

특정 단어로 시작하는지 검사
아래 예제는 검색 대상 문자열이 'http://' 또는 'https://'로 시작하는지 검사한다. [...] 바깥의 ^은 문자열의 시작을 의미하고, ?는 앞선 패턴(s)이 최대 한번 이상 반복되는지를 확인한다.

const url = 'https://example.com';
/^https?:\/\//.test(url); // true

특정 단어로 끝나는지 검사
'$'는 문자열의 마지막을 의미한다.

const fileName = 'index.html';

/html$/.test(fileName); // true

숫자로만 이루어진 문자열인지 검사
다음 예제는 처음과 끝이 숫자이고 최소 한번 이상 반복되는 문자열인지 매치한다. [...] 바깥의 ^은 문자열의 시작을, $는 문자열의 마지막을 의미한다. \d는 숫자를 의미하고 +는 앞선 패턴이 최소 한 번 이상 반복되는 문자열을 의미한다.

const target = '12345';

/^\d+$/.test(target); // true

하나 이상의 공백으로 시작하는지 검사
다음 예제는 검색 대상 문자열이 하나 이상의 공백으로 시작하는지 검사한다. \s 는 여러 가지 공백 문자를 의미한다.

const target = '  Hi!';

/^[\s]+/.test(target); // true

아이디로 사용 가능한지 검사
다음 예제는 검색 대상 문자열이 알파벳 대소문자 또는 숫자로 시작하고 끝나면 4~10자리인지 검사한다.

const id = 'abc123';

/^[A-Za-z0-9]{4,10}$/.test(id); // true

핸드폰 번호 형식에 맞는지 검사
다음 예제는 검색 대상 문자열이 핸드폰 번호 형식에 맞는지 검사한다.

const cellphone = '010-1234-5678';

/^\d{3}-\d{3,4}-\d{4}$/.test(cellphone); // true

특수 문자 포함 여부 검사
다음 예제는 검색 대상 문자열에 특수 문자가 포함되어 있는지 검사한다.

const target = 'abc#123';

(/[^A-Za-z0-9]/gi).test(target); // true

특수 문자를 제거할 때는 replace 메서드를 사용한다.

target.replace(/[^A-Za-z0-9]/gi, ''); // abc123
profile
블로그 이전했습니다

0개의 댓글