[JS] 모던 Javascript Deep Dive 31장 - RegExp
업데이트:
정규 표현식을 드디어 배운다.
외계 문자 같아서 왠지 공부하기 싫었던 파트이다. 이번 기회에 제대로 개념을 정리해보자 !
[01] 정규표현식이란?
📌 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어
정규표현식은 자바스크립트 고유 문법이 아니고 펄(Perl)의 정규 표현식 문법을 ES3부터 도입한 것이라고 한다.
const tel = '010-2345-678';
const regExp = /^\d{3}-\d{4}-\d{4}$/;
regExp.test(tel); // false
위처럼 문자열을 대상으로 패턴 매칭 기능을 제공한다.
[02] 정규 표현식의 생성
정규 표현식은 객체이고 정규 표현식 리터럴과 RegExp 생성자 함수를 사용할 수 있다.
일반적으로는 정규 표현식 리터럴을 많이 사용한다.
정규 표현식 리터럴은 패턴과 플래그로 구성된다.
아래는 문자열 안에 ‘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
맺음말
생각보다 표현하는 기호들이 많아서 정리를 해도 너무 헷갈리는 것 같다.
그래도 이젠 어려운 정규표현식을 봐도 해석할 수는 있으니 나름 발전했다 ..
이번 파트는 책 내용만 이해하고 넘어가기보다는 스터디원들과 문제도 많이 풀어보며 더 공부해야겠다 !
댓글남기기