이번 장에서는 자바스크립트의 정규표현식에 대해서 알아보겠습니다.
정규표현식은 자바스립트의 고유한 문법은 아닙니다.
대부분의 프로그래밍 언어에 내장되어있습니다.
그만큼 범용성이 있는 기능이며, 정규표현식을 잘 알고 있으면 문자 검색과 교체를 원하는 대로 조작할 수 있습니다. 이제 정규표현식에 대해서 얕게 알아보겠습니다.
정규 표현식(regular expression)은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. - 위키백과
간단한 예시를 보겠습니다.
const filename = 'test.gif';
if (/\.jpg|\.png|\.gif/.test(filename)) {
console.log('jpg/png/gif 파일이 맞음.');
} else {
console.log('원하는 파일이 아님.');
}
//실행결과 : jpg/png/gif 파일이 맞음.
원하는 파일 형식을 찾을 때 정규표현식으로 찾으면 단 몇 줄이면 됩니다. 하지만 정규식을 사용하지 않는다면 어떻게 만들지 벌써부터 막막하기만 합니다.
정규 표현식은 패턴과 플래그로 구성되어 있습니다.
정규식 객체를 만들 때는 두 가지 방법이 있습니다.
regexp = new RegExp('패턴', '플래그');
regexp = /패턴/; // 플래그 없음
regexp = /패턴/igmsuy; // 플래그 i, g, m, s, u, y 있음.
두 문법의 차이점을 보면, /패턴/을 사용한 방법은 문자열 템플릿 리터럴에서 ${변수}를 한 것처럼 변수에 /패턴/을 넣을 수 없습니다. /패턴/은 정적이기 때문입니다.
반대로 첫 번째 방법인 new RegExp를 사용한 방법은 동적으로 생성된 문자열을 가지고 정규 표현식을 만들 때 사용할 수 있습니다.
let string = prompt('찾고 싶은 문자열이 무엇인가요?');
let regExp = new RegExp(`${string}`);
자바스크립트에서 지원하는 플래그는 아래와 같습니다.
①. i - 대·소문자 구분 없이 검색합니다.
②. g - 패턴과 일치하는 모든 것을 찾습니다.
③. m - multiline mode의 약어로, 다중 행 모드를 활성화 시킵니다.
④. s - .이 개행 문자 \n도 포함하도록 'dotall'모드를 활성화 시킵니다.
⑤. u - 유니코드를 지원합니다.
⑥. y - 'sticky'모드를 활성화 시킵니다.
replace() 메서드는 패턴에 일치하는 부분을 새로운 문자열로 반환합니다.
let str = 'Hello World, world, World';
let str2 = str.replace("World", "친구들");
console.log(str2); // Hello 친구들, world, World
정규표현식을 사용할 때
let str = 'Hello World, world, World';
let regExp = /World/gi; // 플래그 g는 모든 문자열에 해당, i는 대·소문자 구문하지 않음
console.log(str.replace(regExp, '친구들')); // Hello 친구들, 친구들, 친구들
match() 메서드는 문자열이 정규식과 맞는 부분을 검색합니다.
// 문법
str.match(regexp)
매개변수
반환 값
let str = '12345abcde6789fghi0';
// 정규식 일치
let regExp = /[a-z]{2}/g; // [a-z]{2}는 소문자 2자리
let result = str.match(regExp);
console.log(result); // (4) ['ab', 'cd', 'fg', 'hi']
// 정규실 불일치
let regExp2 = /hello/;
let result2 = str.match(regExp2);
console.log(result2); // null
search() 메드는 정규식과 문자열 간의 일치함을 검색해 줍니다.
// 문법
str.search(regexp)
let welcome = 'Hello Word! This is JavaScript!';
// 정규식 일치
let regExp = /JavaScript/;
let result = welcome.search(regExp);
console.log(result); // 20
// 정규식 불일치
let regExp2 = /John/;
let result2 = welcome.search(regExp2);
console.log(result2); // -1
test() 메서드는 주어진 문자열이 정규식을 만족하는지 판별한 후 그 여부를 true/false로 반환합니다.
// 문법
regexpObj.test(str)
// str은 정규식 일치를 확인할 문자열 입니다.
let str = 'Hello World, world, World';
// 정규식 불일치
let regExp = /Helo/;
console.log(regExp.test(str)); // false
// 정규식 일치
let regExp2 = /Hello/;
console.log(regExp2.test(str)); // true
이제 정규표현식을 자주 쓰는 예시 2가지를 보도록 하겠습니다.
stackoverflow나 구글링을 하면서 전화번호나 이메일 정규식 패턴을 구문 이해 없이 복사·붙여넣기 한다면, 정규식에 대한 깊은 이해를 할 수 없습니다.
이번의 간단한 예시를 통해서 정규식에 대한 친밀감을 한발짝 다가갔으면 합니다.
let tel = '010-1234-5678';
let regExp = /^010-\d{4}-\d{4}$/;
console.log(regExp.test(tel)); // true
console.log(tel.search(regExp)); // 010
console.log(tel.match(regExp)); // ['010-1234-5678', index: 0, input: '010-1234-5678', groups: undefined]
정규식 설명
let email = 'heung7min.son@gmail.com';
let wrongEmail = 'wrongWrong@gmail';
let regExp = /^([a-z]+\d*)+(\.?[a-z]+\d*)+@([a-z]+\d*)+(\.[a-z]{2,3})+$/;
console.log(regExp.test(email)); // true
console.log(regExp.test(wrongEmail)); // false
정규식 설명
/*
** 문제. 사용자가 입력한 아이디를 파라미터로 받고,
** 사용자 아이디가 다음 조건을 만족하는지 확인하는 함수를 작성하세요. (함수명: checkUserId(userId))
**
** 조건
** 1. [O] 사용자 아이디는 5자리 이상 15자리 이하입니다.
** 2. [O] 알파벳 소문자, 숫자, 밑줄(_), 마침표(.)만 포함할 수 있습니다.
** 3. [O] 밑줄은 연속해서 2개 사용할 수 없습니다.
** 4. [O] 마침표는 1개만 사용할 수 있습니다.
** 5. [O] 아이디 시작은 반드시 소문자여야 합니다.
** 6. [O] 아이디 마지막 문자는 소문자 또는 숫자만 가능합니다.
** 7. [O] 조건을 만족하면 true, 만족하지 않으면 false 반환하세요.
*/
function checkUserId(userId) {
// ...
}
Answer 👈function checkUserId(userId) {
// 조건1
const lenRegExp = /^.{5,15}$/;
if (!lenRegExp.test(userId)) return false;
// 조건 2
const regExp = /[a-z0-9_\.]+/; // 언더바(_)는 \ 필요없음
if (!regExp.test(userId)) return false;
// 조건 2 (Way 2)
// if (/[^a-z0-9\_\.]+/.test(userId)) return false; // [^~~~]는 ~~~의 부정이라는 말임
// 조건 3
const regExp2 = /_{2}/; // /__/g 할 필요없음
if (regExp2.test(userId)) return false;
// 조건 4
if(userId.split('.').length > 2) return false;
// 조건 5
if(!/^[a-z]/.test(userId)) return false;
// 조건 5 (Way 2)
//if(/^[^a-z]/.teest(userId)) return false; // [^a-z]는 소문자가 아니면 이라는 뜻!
// 조건 6
if(!/[a-z0-9]$/.test(userId)) return false;
return true;
}
// TEST CASES
// 여러 자릿수의 문자열
// 4자리 문자열
console.log(checkUserId('a234')); // false
// 5자리 문자열
console.log(checkUserId('a1234')); // true
// 15자리 문자열
console.log(checkUserId('a12345678901234')); // true
// 16자리 문자열
console.log(checkUserId('a123456789012345')); // false
// 알파벳, 소문자, 숫자, 밑줄(_), 마침표(.) 만 들어간 문자열
console.log(checkUserId('abcde')); // true
console.log(checkUserId('abcde1')); // true
console.log(checkUserId('ab.cde1')); // true
console.log(checkUserId('ab_cde1')); // true
// 알파벳, 소문자, 숫자, 밑줄(_), 마침표(.) 말고도 다른 문자가 들어간 문자열
console.log(checkUserId('a#bcde')); // false
console.log(checkUserId('abc^de')); // false
console.log(checkUserId('abc de')); // false
// 밑줄 1개 사용
console.log(checkUserId('abc_de')); // true
// 밑줄 연속 2개 이상 사용
console.log(checkUserId('abc__de')); // false
console.log(checkUserId('abc___de')); // false
// 밑줄 연속하지 않게 사용
console.log(checkUserId('a._1_b')); // true
// 마침표 1개 사용
console.log(checkUserId('abc.de')); // true
console.log(checkUserId('abcde.')); // true
// 마침표 2개 사용
console.log(checkUserId('abc..de')); // false
console.log(checkUserId('a.bc.d.de')); // false
// 시작이 소문자
console.log(checkUserId('abcde')); // true
// 시작이 소문자가 아닌 경우
console.log(checkUserId('Abcde')); // false
console.log(checkUserId('1bcde')); // false
console.log(checkUserId('.bcde')); // false
console.log(checkUserId('_bcde')); // false
console.log(checkUserId('@bcde')); // false
// 마지막 문자가 소문자 또는 숫자인 경우
console.log(checkUserId('abcde')); //true
console.log(checkUserId('abcd1')); //true
console.log(checkUserId('ab.cd1')); //true
console.log(checkUserId('ab.cd1')); //true
console.log(checkUserId('a_b.c_d1')); //true
console.log(checkUserId('a_b.c_.d1')); //false
console.log(checkUserId('a_b.c__d1')); //false
console.log(checkUserId('a_b.c_8_d1')); //true
// 마지막 문자가 소문자 또는 숫자가 아닌 경우
console.log(checkUserId('abcd.')); //false
console.log(checkUserId('abcd_')); //false
console.log(checkUserId('abcdA')); //false
console.log(checkUserId('abcd@')); //false