업데이트:

정규 표현식을 드디어 배운다.

외계 문자 같아서 왠지 공부하기 싫었던 파트이다. 이번 기회에 제대로 개념을 정리해보자 !

[01] 정규표현식이란?

📌 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어

정규표현식은 자바스크립트 고유 문법이 아니고 펄(Perl)의 정규 표현식 문법을 ES3부터 도입한 것이라고 한다.

const tel = '010-2345-678';
const regExp = /^\d{3}-\d{4}-\d{4}$/;
regExp.test(tel); // false

위처럼 문자열을 대상으로 패턴 매칭 기능을 제공한다.

[02] 정규 표현식의 생성

정규 표현식은 객체이고 정규 표현식 리터럴과 RegExp 생성자 함수를 사용할 수 있다.

일반적으로는 정규 표현식 리터럴을 많이 사용한다.

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

Untitled

아래는 문자열 안에 ‘is’라는 문자열이 있는지 검색하는 정규표현식 코드이다.

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

const regexp = /is/i; // 플래그 i : 대소문자를 구별하지 않고 문자열 검색
//const regexp = new RegExp(/is/i); 로도 표현 가능

regexp.test(target); // true

[03] RegExp 메서드

RegExp.prototype.exec

전달받은 문자열에 대해 매칭 결과를 배열로 반환

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

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

g플래그로 지정하면 첫 번째 매칭 결과만 반환

RegExp.prototype.test

정규 표현식의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환

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

regExp.test(target) // true

String.prototype.match

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

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

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

match 메서드는 g 플래그가 지정되면 모든 매칭 결과를 배열로 반환

[04] 플래그

플래그는 총 6개 있는데 그 중 중요한 3가지이다.

플래그 의미 설명
i Ignore case 대소문자를 구별하지 않고 패턴을 검색
g Global 대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색
m Multi line 문자열의 행이 바뀌어도 패턴 검색을 계속함.

[05] 패턴

패턴은 /로 열고 닫으며 문자열의 따옴표는 생략한다.

패턴은 특별한 의미를 가지는 메타문자나 기호로 표현할 수 있다.

패턴을 표현하는 방법들에 대해 알아보자

문자열 검색

위에서 공부했던 메서드 방식과 플래그를 이용하여 정규 표현식의 매칭 결과를 구할 수 있다.

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

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

플래그 두개를 이어서 각 플래그의 기능을 합칠 수도 있다.

임의의 문자열 검색( .)

. 은 임의의 문자 한 개를 의미한다.

const target = 'Is this all there is?';
const regExp = /.../g;
target.match(regExp); // ["Is ", "thi", "s a", "ll ", "the", "re ", "is?"]
// 점이 3개이므로 문자 3개씩 매치했다.

반복 검색

최소 m번 최대 n번 반복되는 문자열을 의미한다.

  • m과 n사이의 콤마 뒤에 공백이 있으면 안된다.
  • {n}은 {n,n}과 같다.
  • {n,}은 앞선 패턴이 최소 n번 이상 반복되는 문자열을 의미한다.
const target = 'A AA B BB Aa Bb AAA';
const regExp = /A{1,2}/g;
target.match(regExp); // ["A" "AA", "A", "AA", "A"]
const regExp2 = /A{2}/g;
target.match(regExp2); // ["AA", "AA"]
const regExp3 = /A{2,}/g;
targe.match(regExp3); // ["AA", "AAA"]
  • +는 앞선 패턴이 최소 한번 이상 반복되는 문자열을 의미한다.
  • ? 는 앞선 패턴이 최대 한 번 이상 반복되는 문자열을 의미한다.
const target = 'A AA B BB Aa Bb AAA';
const regExp = /A+/g;
target.match(regExp); // ["A", "AA", "A", "AAA"]

const target2 = 'color colour';
const regExp2 = /colou?r/g;
target2.match(regExp2); // ["color", "colour"]

OR 검색

은 or의 의미를 갖는다.
const target = 'A AA B BB Aa Bb';
const regExp = /A|B/g; 
target.match(regExp); // ["A", "A", "A", "B", "B", "B", "A", "B"]

+를 함께 사용하면 분해되지 않은 단어 레벨로 검색한다.

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 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;
const regExp2 = /[0-9]+/g;
target.match(regExp); // ["AA", "BB", "Aa", "Bb"]
target.match(regExp2); // ["12"]

숫자를 찾는 방법인 /[0-9]//[\d]/ 와 결과가 같다.

\d 는 숫자를 의미하고 \D는 문자를 의미한다.

const targetStr = 'AA BB Aa Bb 24,000';

// '0' ~ '9' 또는 ','가 한번 이상 반복되는 문자열을 반복 검색
let regexr = /[\d,]+/g;

console.log(targetStr.match(regexr)); // [ '24,000' ]

// '0' ~ '9'가 아닌 문자(숫자가 아닌 문자) 또는 ','가 한번 이상 반복되는 문자열을 반복 검색
regexr = /[\D,]+/g;

console.log(targetStr.match(regexr)); // [ 'AA BB Aa Bb ', ',' ]

\w 는 알파벳과 숫자, 언더스코어를 의미한다. \W는 \w와 반대로 동작한다.

const target = 'Aa Bb 12,345 _$%&';
let regExp = /[\w,]+/g;
target.match(regExp); // ["Aa", "Bb", "12,345", "_"]
regExp = /[\W,]+/g;
target.match(regExp); // [" ", " ", ",", " ", " $%&"]

NOT 검색

[ ] 내에서 ^를 앞에 붙이면 원래 기능과 반대의 의미를 갖는다.

const target = 'AA BB 12 Aa Bb';
const regExp = /[^0-9]+/g;
target.match(regExp); // ["AA BB ", " Aa Bb"]

시작 위치로 검색

[ ] 밖에서 ^를 붙이면 문자열의 시작을 의미한다.

const target = "https://naver.com";
const regExp = /^https/;
regExp.test(target); // true

마지막 위치로 검색

$는 문자열의 마지막에 패턴이 있는지 검색한다.

const target = "https://naver.com";
const regExp = /com$/;
regExp.test(target); // true

🔍 여러가지 검색 기호 정리

  기능  
/ … / 플래그 안의 패턴으로 문자열 검색  
. 임의의 문자 한개를 의미, … 이면 임의의 문자 3개  
{m,n} 최소 m번 최대 n번 반복되는 문자를 의미  
{n} n번 반복되는 문자를 의미  
{n,} n번 이상 반복되는 문자를 의미  
? 앞선 패턴이 최대 한번이상(0번포함) 반복  
+ 앞선 패턴이 최소 한번이상 반복  
\d 숫자를 의미  
\D 문자를 의미  
\w 알파벳과 숫자, 언더스코어를 의미  
\W 알파벳과 숫자, 언더스코어가 아닌 문자  
    or의 의미를 가짐
+ 단어 레벨로 검색  
[ ] 패턴을 대괄호 안에 넣으면 or과 똑같이 동작,  
[ - ] 범위가 지정되어 - 범위 내에서 검색  
[ ] 내에서 ^ NOT의 의미를 가짐  
[ ] 밖에서 ^ 문자열의 시작에 패턴이 있는지 검색  
$ 문자열의 끝에 패턴이 있는지 검색  

[06] 자주 사용하는 정규표현식

특정 단어로 시작하는지 검사

const url = "https://naver.com";
const regexp = /^https?:\/\//;
console.log(regexp.test(url)); // true

https:// 나 http:// 로 시작하는지 검사하는 정규표현식이다.

?는 0번 이상 반복되는지를 의미한다. 그래서 s가 있어도 되고 없어도 된다는 것을 의미한다.

특정 단어로 끝나는지 검사

const fileName = 'index.html';

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

숫자로만 이루어진 문자열인지 검사

const target = '12345';
/^d+$/.test(target); // true

하나 이상의 공백으로 시작하는지 검사

const targe = " Hi!";
/^[\s]+/.test(target) // true
// \s는 여러가지 공백 문자를 의미한다.(탭이나 스페이스)

아이디로 사용 가능한지 검사

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

알파벳 대소문자, 숫자로 시작하고 끝나는지, 4~10자리인지 검사

메일 주소 형식에 맞는지 검사

const email = 'minhye@naver.com';
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}%/.test(email);

핸드폰 번호 형식에 맞는지 검사

const cellphone = '010-1234-5678';

const regexr = /^\d{3}-\d{3,4}-\d{4}$/;

console.log(regexr.test(cellphone)); // true

특수 문자 포함 여부 검사

const targetStr = 'abc#123';

// A-Za-z0-9 이외의 문자가 있는지 검사
let regexr = /[^A-Za-z0-9]/gi;

console.log(regexr.test(targetStr)); // true

// 아래 방식도 동작한다. 이 방식의 장점은 특수 문자를 선택적으로 검사할 수 있다.
regexr = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi;

console.log(regexr.test(targetStr)); // true

// 특수 문자 제거
console.log(targetStr.replace(regexr, '')); // abc123

맺음말

생각보다 표현하는 기호들이 많아서 정리를 해도 너무 헷갈리는 것 같다.

그래도 이젠 어려운 정규표현식을 봐도 해석할 수는 있으니 나름 발전했다 ..

이번 파트는 책 내용만 이해하고 넘어가기보다는 스터디원들과 문제도 많이 풀어보며 더 공부해야겠다 !

댓글남기기