-
기초적인 정규 표현식 이해하기JavaScript 2021. 10. 10. 23:25
개발에 발을 담근(?) 이후 정규 표현식에 대해 들어본적은 많으나 직접 사용해본 적은 한번도 없었다.
알고리즘 문제를 풀때 가끔 정규표현식을 사용하는 사람을 보고 '오 이게 대체 뭐지~ 머리아프다' 하고 지나만 갔다.
하지만 회사 동료의 설명을 잠깐 듣고 나니, 이참에 한번 공부해보자 싶어서 정리해본다.
(설명은 자바스크립트를 기반으로 했습니다)
정규 표현식과 플래그
두 슬래시(/) 사이에 글자를 써넣어서 정규 표현식을 작성할 수 있다.
정규식 관련 메서드로는 match, test, replace 등이 있다 (여기서 replace는 생략함)
test : test 이후 오는 문자열이 regExp와 일치하는지 true/false 를 반환받는다.
match : 문자열에서 regExp 와 일치하는 것들을 찾아내서 반환받는다.
let regExp = /헬로월드/ alert(regExp.test("헬로월드")) // true alert("헬로월드".match(regExp)) // 헬로월드
검색에 영향을 주는 플래그는 6개가 존재한다. 플래그는 여러가지를 합쳐서 쓸 수 있다.
- i - 대소문자 구분 없이 검색
- g - 패턴과 일치하는 모든 것들을 찾음. g 플래그가 없으면 일치하는 첫번째 결과만 반환
- m - 다중 행 모드를 활성화. 다음 행에 오는 문자를 패턴의 첫 문자로 인식함 (^을 쓸 경우 다중 행 모드가 없으면 문자열 첫 시작 이후론 첫 문자로 인식하지 않음)
- s - . 이 개행문자 \n 도 포함하도록 함
- u - 유니코드 전체를 지원
- y - 문자 내 특정 위치에서 검색을 진행하는 'sticky'모드 활성화
let str = "Java JavaScript Python"; alert( str.match(/java/) ); // null alert( str.match(/java/i) ); // Java alert( str.match(/java/gi) ); // Java, Java
[ ] : 후보군이자 범위
- [ ] 안에 있는 글자들은 or 로 이어져서, 그 중 한 문자가 들어가 있으면 일치하는 것으로 판단한다.
alert("classA".match(/class[ABC]/g)); // classA alert("class".match(/class[ABC]/g)); // null -> A,B,C 셋 중 하나가 있어야함
- [ ] 안에 - 를 사용해서 범위를 표현할 수 있다
alert("classA".match(/class[A-Z]/g)); // classA alert("class1A".match(/class[0-9A-Z]/g)); // class1 -> 0~9, A~Z 중 하나 alert("class다".match(/class[가-힣]/g)); // class다 -> 한글도 된다! // - 자체를 찾으려면 escape(\) 사용 alert("class-A".match(/class[A-Z\-]A/g)); // class-A
- [^..] 로 여집합을 표현할 수 있다
alert("classA".match(/class[^BC]/g)); // classA -> B,C 제외라 일치 alert("classB".match(/class[^BC]/g)); // null
- 아래와 같이 간략하게 표현하는 것도 가능하다
- \d : 어떤 하나의 숫자 = [0-9]
- \w : 어떤 하나의 문자 = [a-zA-Z0-9_]
- \s : 공백 하나 = [\t\n\v\f\r]
- \D : \d의 여집합 = [^0-9]
- \W : \w의 여집합 = [^a-zA-Z0-9_]
- \S : \s의 여집합 = [^\t\n\v\f\r]
자주 등장하는 표현식들
표현식 설명 (x) 소괄호로 문자를 묶어서 그룹으로 사용 x{n} x가 n번 반복됨 x{n,} x가 n번 이상 반복됨 x{n,m} x가 최소 n번 이상, 최대 n번 이하 반복됨 x* x가 0번 이상 반복됨 x+ x가 1번 이상 반복됨 x? x가 있거나 없음(0번 or 1번) ^x x로 시작함 x$ x로 끝남
고객 휴대폰 번호 입력 받기
프로젝트에 정규식이 들어간 코드가 딱 두 개가 있어서 확인을 해봤다.
기존 프로젝트 코드에 들어가 있는 휴대폰 번호 정규식은 아래와 같았다.
/^(01[0-9]{1})[0-9]{3,4}[0-9]{4}$/
앞에서부터 차근차근 풀이하자면
^(01[0-9]{1}) : 010 ~ 019 까지의 세 문자가 한 번 반복되는걸로 문자열이 시작된다 (ex. 010)
[0-9]{3,4} : 숫자가 3번 이상, 4번 이하로 반복된다 (ex. 123)
[0-9]{4}$ : 숫자가 4번 반복된 후 문자열이 끝난다 (ex. 4567)
굳이 여기서 [0-9]를 안쓰고, \d로 써도 결과는 같다.
/^(01\d{1})\d{3,4}\d{4}$/
위 정규 표현식을 사용할 경우 누군가 010-9999-9999 를 입력한다면 올바르지 않은 휴대폰번호로 인식할 것이다.
-를 쓰고 안쓰더라도 영향을 안주고싶다면 ? 를 사용하면 된다.
/^(01\d{1})-?\d{3,4}-?\d{4}$/
고객 출생년도 입력받기
두 번째 코드는 출생년도를 입력받는 코드다.
/^(19[0-9][0-9]|20\d{2})$/
짧은 식이라 위 전화번호를 읽었다면 쉽게 이해할 수 있다.
19xx 년으로 표시되거나 20xx 년으로 표시된다면 유효한 출생년도로 인정해주고 있다. (|는 or 연산자로 사용된다)
[0-9]를 또 \d로 바꾸면 아래와 같다.
/^(19\d{2}|20\d{2})$/
이렇게 고치고 보니 더 간결해질 수 있겠다 싶어서 아래처럼 만들었다.
/^(19|20)\d{2}$/
이메일 입력받기
기존 코드에는 없지만, 만약 유효한 이메일을 입력받으려면 어떻게 해야할까?
이건 어떤 형태가 올바른 이메일이냐에 대한 결정에 따라서 다양한 답이 나올 수 있을 것 같다.
^[A-Za-z0-9](\w|[.-])*@[A-Za-z0-9](\w|[.-])*\.(com|co.kr)$
위는 내가 생각해본 답이다. 생각한 조건은 아래와 같다.
1. 아이디와 도메인명의 시작은 [A-Za-z0-9] 가 허용된다 (\w를 쓰고 싶었으나 \w에는 _가 포함되어 있다ㅜㅜ)
2. 아이디와 도메인명의 시작 외 나머지 부분은 전체 문자(\w) 및 . - 가 올 수 있다
3. 아이디와 도메인명 사이에는 @ 가 있다
4. .com 혹은 .co.kr 로 끝난다
아래 링크에서 정규 표현식을 쉽게 테스트해볼수 있다
'JavaScript' 카테고리의 다른 글
[html] 웹페이지에 네이버 지도 넣기 (NAVER Map API) (0) 2021.12.05 DOM 이란? (0) 2021.11.21 호이스팅(Hoisting)이란? (0) 2021.11.07