RegExp, 정규 표현식이란?
정규 표현식, 또는 정규식은 문자열에서 특정 문자 조합을 찾기 위한 패턴이다.
JavaScript에서는 정규 표현식도 객체로서, RegExp의 exec()와 test() 메서드를 사용할 수 있다.
String의 match(), matchAll() (en-US), replace(), replaceAll(), search(), split() 메서드와도 함께 사용할 수 있다.
정규 표현식 만들기
정규 표현식 객체를 생성하려면 정규 표현식 리터럴이나 RegExp 생성자 함수를 사용해야 한다.
일반적으로는 정규 표현식 리터럴을 사용한다.
정규 표현식 리터럴
- 다음과 같이 슬래시로 패턴을 감싸서 작성한다.
- 정규 표현식 리터럴은 스크립트를 불러올 때 컴파일되므로, 바뀔 일이 없는 패턴의 경우 리터럴을 사용하면 성능이 향상될 수 있다.
1
2
| // /(패턴)/i
const re = /ab+c/
|
RegExp 객체의 생성자 호출
- 생성자 함수를 사용하면 정규 표현식이 런타임에 컴파일된다.
- 바뀔 수 있는 패턴이나, 사용자 입력 등 외부 출처에서 가져오는 패턴의 경우 이렇게 사용한다.
1
| const re = new RegExp('ab+c')
|
HTML에서 정규식 사용하기
1
| <input pattern="정규표현식">
|
- HTML5에서 새롭게 추가된 속성이다.
<input> 태그의 pattern 속성은 폼 제출 시 <input> 요소의 값을 검사할 때 사용될 정규 표현식(regular expression)을 명시한다.- 이때 전역 속성인 title 속성을 사용하여 정규 표현식에 간단한 설명을 추가함으로써 사용자가 정확한 값을 입력할 수 있도록 도움을 줄 수 있다.
- 보안상 예상치 않은 데이터 입력을 완전하게 컨트롤 하기 위해서는 최종적으로 서버사이드 스크립트에서 처리해 주어야 한다.
- pattern 속성이 제대로 동작하는
<input>요소의 type 속성값은 다음과 같다.- date, email, password, search, tel, text, url
정규 표현식 패턴 작성하기
출처: https://hamait.tistory.com/342
정규 표현식의 용어들정규 표현식에서 사용되는 기호를 Meta문자라고 표현한다. 표현식에서 내부적으로 특정 의미를 가지는 문자를 말하며 간단하게 정리하면 아래의 표와 같다.
| 표현식 | 의미 |
|---|
^x | 문자열의 시작을 표현하며 x 문자로 시작됨을 의미한다. |
x$ | 문자열의 종료를 표현하며 x 문자로 종료됨을 의미한다. |
.x | 임의의 한 문자의 자리수를 표현하며 문자열이 x 로 끝난다는 것을 의미한다. |
x+ | 반복을 표현하며 x 문자가 한번 이상 반복됨을 의미한다. |
x? | 존재여부를 표현하며 x 문자가 존재할 수도, 존재하지 않을 수도 있음을 의미한다. |
x* | 반복여부를 표현하며 x 문자가 0번 또는 그 이상 반복됨을 의미한다. |
x\|y | or 를 표현하며 x 또는 y 문자가 존재함을 의미한다. |
(x) | 그룹을 표현하며 x 를 그룹으로 처리함을 의미한다. |
(x)(y) | 그룹들의 집합을 표현하며 앞에서 부터 순서대로 번호를 부여하여 관리하고 x, y 는 각 그룹의 데이터로 관리된다. |
(x)(?:y) | 그룹들의 집합에 대한 예외를 표현하며 그룹 집합으로 관리되지 않음을 의미한다. |
x{n} | 반복을 표현하며 x 문자가 n번 반복됨을 의미한다. |
x{n,} | 반복을 표현하며 x 문자가 n번 이상 반복됨을 의미한다. |
x{n,m} | 반복을 표현하며 x 문자가 최소 n번 이상 최대 m 번 이하로 반복됨을 의미한다. |
좀 더 특별한 용도로 사용되는 것들
Meta 문자들 중에서 좀 더 특수하게 사용되는 문자들이 존재한다. ‘[]’ 는 내부에 지정된 문자열의 범위 중에서 한 문자만을 선택하다는 특수한 의미를 가진다. 그리고 내부에서 Meta문자를 사용하면 다른 의미를 가지고 동작할 수 있으므로 잘 확인하고 사용해야 한다. 좀 더 특별한 용도로 사용되는 것들은 아래의 표와 같다.
| 표현식 | 의미 |
|---|
[xy] | 문자 선택을 표현하며 x 와 y 중에 하나를 의미한다. |
[^xy] | not 을 표현하며 x 및 y 를 제외한 문자를 의미한다. |
[x-z] | range를 표현하며 x ~ z 사이의 문자를 의미한다. |
\^ | escape 를 표현하며 ^ 를 문자로 사용함을 의미한다. |
\b | word boundary를 표현하며 문자와 공백사이의 문자를 의미한다. |
\B | non word boundary를 표현하며 문자와 공백사이가 아닌 문자를 의미한다. |
\d | digit 를 표현하며 숫자를 의미한다. |
\D | non digit 를 표현하며 숫자가 아닌 것을 의미한다. |
\s | space 를 표현하며 공백 문자를 의미한다. |
\S | non space를 표현하며 공백 문자가 아닌 것을 의미한다. |
\t | tab 을 표현하며 탭 문자를 의미한다. |
\v | vertical tab을 표현하며 수직 탭(?) 문자를 의미한다. |
\w | word 를 표현하며 알파벳 + 숫자 + _ 중의 한 문자임을 의미한다. |
\W | non word를 표현하며 알파벳 + 숫자 + _ 가 아닌 문자를 의미한다. |
플래그
플래그의 역할은 정규 표현식의 검색 방식을 설정하는 것이다. 플래그에는 총 여섯가지가 있다.
플래그는 옵션이다. 또한 순서와 상관없이 하나 이상의 플래그를 동시에 사용할 수도 있다.
| flag | meaning | detail |
|---|
i | Ignore | Casing 대소문자 구별 없이 패턴 검사 |
g | Global | 패턴과 일치하는 모든 문자열 전역 검색 |
s | Dot All | .(온점)이 개행 문자(\n)도 포함 |
m | Multiline | 행이 바뀌어도 계속 검색 |
y | Sticky | 문자 내 특정 위치에서 검색을 시작 |
u | Unicode | 유니코드 전체 지원 |
d | - | 부분 문자열 일치에 대해 인덱스 생성 |
정규식 메서드
위의 정규표현식을 가지고 이메일이나 전화번호 매칭 필터링을 하기 위해선 자바스크립트 정규식 메서드를 이용하여 패턴을 검사하고, 매칭되는 문자열을 추출, 변환한다.
정규표현식은 RegExp의 메서드 test()와 exec(), String의 메서드 match(), replace(), search(), split() 에서 사용할 수 있다.
match()
- 캡처 그룹을 포함해서 모든 일치를 담은 배열을 반환한다. 일치가 없으면 null을 반환한다.
("문자열").match(/정규표현식/플래그)
matchAll()
- 캡쳐 그룹을 포함해서 모든 일치를 담은 반복기를 반환한다.
- (en-US)
search()
- 문자여렝서 일치하는 부분을 탐색한다. 일치하는 부분의 인덱스, 또는 일치가 없는 경우 -1을 반환한다.
replace()
- 문자열에서 일치하는 부분을 탐색하고, 그 부분을 대체 문자열로 바꿔준다.
("문자열").replace(/정규표현식/, "대체문자열")
replaceAll()
- 문자열에서 일치하는 부분을 모두 탐색하고, 모두 대체 문자열로 바꾼다.
split()
- 정규 표현식 또는 문자열 리터럴을 사용해서 문자열을 부분 문자열의 배열로 나눈다.
("문자열").split(정규표현식)
test()
- 문자열에 이치하는 부분이 있는지 확인한다. true 또는 false를 반환한다.
(정규표현식).test("문자열")
exec()
- 문자열에서 일치하는 부분을 탐색한다. 일치 정보를 나타내는 배열, 또는 일치가 없는 경우 null을 반환한다.
const myRe = /d(b+)d/g;const myArray = myRe.exec('cdbbdbsbz');
문자열 내부에 패턴과 일치하는 부분이 존재하는지만 알아내려면 test()나 search() 메서드를 사용하자.
더 느리더라도 일치에 관한 추가 정보가 필요하면 exec()과 match() 메서드를 사용하자. 일치하는 부분이 존재하면, exec()과 match()는 일치에 관한 데이터를 포함한 배열을 반환하고, 일치에 사용한 정규 표현식 객체의 속성을 업데이트한다. 일치하지 못한 경우 null을 반환한다. (null은 조건 평가 시 false와 같다)
사용 예제
- 개별 숫자
/[0-9]/g- 전체에서 0~9사이에 아무 숫자 ‘하나’ 찾음
/[to]/g
- 단어
/filter/g- 전체에서 f 따로 i 따로 찾는게 아니라 ‘filter’ 라는 단어에 매칭되는것을 찾음
- 단어 제외
/\b(?:(?!to)\w)+\b/g- 전체에서 ‘to’ 라는 단어를 빼고 다른 단어 매칭
- 확인결과 “Tutorial” 도 제외 됨
\b(?!\bto\b)\w+\b- 전체에서 ‘to’ 라는 단어를 빼고 다른 단어 매칭
- 확인결과 “Tutorial” 는 제외 안됨. 이게 더 정확하다고 볼 수 있을 듯.
- 이메일
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i^[0-9a-zA-Z]- 숫자(0~9) 또는 영문자(a-z, A-Z)로 시작
([-_\.]?[0-9a-zA-Z])*- 이메일 아이디 부분
- _ . 중 하나가 있을 수도 있고 없을 수도 있으며
- 그 뒤에 숫자 또는 영문자 1개가 오는 패턴 0번 이상 반복
@- 아이디와 이메일을 구분하는 @ 문자가 반드시 1개 존재
[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*- 도메인 이름 부분
- _ . 중 하나가 있을 수도 있고 없을 수도 있으며
- 그 뒤에 숫자 또는 영문자 1개가 오는 패턴이 0번 이상 반복
\.[a-zA-Z]{2,3}$- 최상위 도메인이 영문자 2자 또는 3자로 끝남
- 예: com, net, kr
i: 전체 정규식에서 대소문자를 구분하지 않음
- 전화번호
/^\d{3}-\d{3,4}-\d{4}$/^\d{3}: 시작을 숫자 3개로하며, 그 후에 하이픈 하나 존재\d{3,4}: 숫자가 3~4개 존재하며, 그 후에 하이픈 하나 존재\d{4}$: 숫자 4개로 끝남
- 핸드폰 번호
/^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/^01([0|1|6|7|8|9]?)- 숫자 01로 시작하며, 그 뒤에 0,1,6,7,8,9 중 하나가 올수도 있고 안 올 수도 있음
-?- 하이픈(-) 하나 존재할 수도 있고 생략될 수도 있음
([0-9]{3,4})-?- 다시 하이픈(-)이 하나 존재할 수도 있고 생략될 수도 있음
([0-9]{4})$
- URL
^(https?):\/\/([^:\/\s]+)(:([^\/]*))?((\/[^\s/\/]+)*)?\/?([^#\s\?]*)(\?([^#\s]*))?(#(\w*))?$^: 문자열의 시작(https?)- http또는 https 프로토콜
- s? 로 인해 https의 s는 선택 사항
:\/\/([^:\/\s]+)- 호스트명(domain) 부분
- : / 공백을 제외한 문자 1개 이상
- 예: example.com, localhost
(:([^\/]*))?- 포트 번호 전체가 선택 사항
- :뒤에 /를 제외한 문자 0개 이상
- 예: :80, :3000
((\/[^\s/\/]+)*)?- 경로(path) 부분 전체가 선택 사항
- / 로 시작하며 공백과 / 를 제외한 문자 1개 이상
- 여러 경로 세그먼트를 허용
- 예: /users/123/profile
\/?- 경로의 끝에 슬래시 / 가 있어도 되고 없어도 됨
([^#\s\?]*)- 파일명 또는 마지막 경로 조각
- #, ?, 공백을 제외한 문자 0개 이상
- 예: index.html
(\?([^#\s]*))?- 쿼리 스트링 전체가 선택 사항
- ? 뒤에 # 과 공백을 제외한 문자들
- 예: ?page=1&size=10
(#(\w*))?- 해시(fragment) 전체가 선택 사항
- # 뒤에 영문자, 숫자, 언더스코어 \w
- 예: #section1
$: 문자열의 끝
자주 사용하는 정규표현식
숫자만
1
2
3
4
5
6
| const number = /\d*/
const number = /^\d+$/
const number = /^[0-9]+$/
const number = /[0-9]/
const number = /[^(0-9)]/gi
const number = /^[1-9][0-9]*$/
|
숫자 천 단위마다 콤마(,) 찍기
1
| const number = /\B(?=(\d{3})+(?!\d))/g
|
핸드폰 번호
1
2
3
| const cellphone = '010-1234-5678';
const cellphone = /^\d{3}-\d{3,4}-\d{4}$/;
const cellPhone = /^(?:(010\d{4})|(01[1|6|7|8|9]-\d{3,4}))(\d{4})$/
|
일반 전화번호
- 유선번호라면 02-111-2222 형식이고, 핸드폰번호라면 010-1111-2222 형식을 모두 포함하는 정규식 (숫자의 갯수가 다름)
1
2
3
| const localPhone = /^\d{2,3}-\d{3,4}-\d{4}$/
const localPhone = /\d{2,3}-\d{3,4}-\d{4}/g
const localPhone = /^(0(2|3[1-3]|4[1-4]|5[1-5]|6[1-4]))(\d{3,4})(\d{4})$/
|
\d{2,3}: 숫자 2~3개로 시작하고,\-: 다음에 하이픈(-)이 오고\d{3, 4}: 다음에 숫자가 3~4개 오고,\-: 다음에 하이픈(-)이 오고,\d{4}: 다음에 숫자가 4개 온다.g: 매칭되는걸 모두 다 찾는다(플래그)
특정 단어로 끝나는지 검사
1
2
| const fileName = 'index.html';
const regExp = /html$/;
|
문자 형식
1
2
3
4
| const korea_cv = /[ㄱ-ㅎ|ㅏ-ㅣ]/;
const korea = /[가-힣]/;
const koreaName = /[가-힣]/;
const english = /[a-z | A-Z]/;
|
영문 대소문자만
1
2
| const eng = /^[a-zA-Z]+$/
const eng = /^[a-zA-Z\s]+$/ // 띄어쓰기 및 공백 가능
|
영문 한글만
1
2
| const ko_en_num_charactor = /^[가-힣a-zA-Z0-9]*$/;
const ko_en_charactor = /^[가-힣a-zA-Z]*$/;
|
숫자, 영문, 대소문자만
1
2
| const regExp = /^[a-zA-Z0-9]+$/
const regExp = /^.*(?=.{6,20})(?=.*[0-9])(?=.*[a-zA-Z]).*$/ // 길이 6자 이상, 숫자 최소 1개 포함, 영문자 최소 1개 포함
|
영문 소문자, 숫자, 언더바(_) 6~50자
1
| const regExp = /^([a-z0-9_]){6,50}$/
|
영문자(대소문자) 3~6개 다음에 숫자 3~6개
1
| var id_check = /^[a-z | A-Z]{3,6}[0-9]{3,6}$/
|
영문 대소문자, 숫자, 특수문자를 꼭 포함하여 6~50자
1
| const regExp = /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_-+=[]{}~?:;`|/]).{6,50}$/
|
최소 8자리에서 최대 16자리까지 숫자, 영문, 특수문자 각 1개 이상 포함 (암호 유효성 검사에 유용하다.)
1
| const regExp = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,16}$/
|
영문 대소문자, 숫자, 특수문자를 꼭 포함하여 6~50자
1
| const regExp = ^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_-+=[]{}~?:;`|/]).{6,50}$
|
특수문자 정규표현식
1
2
3
4
5
| const regExp = /\[\]\{\}\/\(\)\.\?\<\>!@#$%^&*/g // 모든 특수기호를 나열
const regExp = /[\{\}\[\]\/?.,;:|\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/;
const regExp = /[^a-zA-Z0-9가-힣ㄱ-ㅎ]/g // 문자와 숫자가 아닌것을 매칭
const comma_char = /,/g; // 콤마
const blank = /[\s]/g; // 공백
|
특수문자만 입력 방지 (한글이나 한자등 일반적인 문자는 모두 입력 가능)
1
| const regExp = /[^!@#$%^&*()_-+=[]{}~?:;`|/<>'"]+/
|
세 개의 문자(아무 숫자나 특수문자)를 포함
1
| const regExp = /[A-Za-z]{3}/
|
숫자·소문자·대문자를 각각 최소 1개 이상 포함하면서 전체 길이가 8자 이상인 문자열만 허용
1
| const regExp = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/
|
알파벳 대소문자 또는 숫자로 시작하고 끝나며 4~10자리인지 검사
1
| const regExp = /^[A-Za-z0-9]{4,10}$/;
|
작은따옴표(‘)와 큰따옴표(“)를 제외한 모든 문자로 이루어진 문자열만 허용
1
| const regExp = /^[^'\x22]+$/
|
이메일 주소 형식
1
2
3
| const text = `http://dogumaster.com http://google.com 010-1111-2222 02-333-7777 curryyou@aaa.com`;
const regExp = /[\w\-\.]+\@[\w\-\.]+/g;
text.match(regExp); // [ 'curryyou@aaa.com' ]
|
- 소문자 영문·숫자·일부 특수문자를 사용하는 아이디와, 2~3자의 영문 최상위 도메인을 가진 이메일 형식만 허용
1
| const regExp = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$/
|
- 좀더 엄격한 검사가 필요하다면, 상황에 맞게 수정해서 사용면 된다.
1
2
3
| const email = 'ungmo2@gmail.com';
const regExp = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/;
const regExp =/([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
|
http:// 또는 https://로 시작하고 그 뒤에 하나 이상의 문자가 반드시 이어지는 URL만 허용
1
| const regExp = /^https?:\/\/.+$/
|
웹사이트 주소 형식
- http:// 나 https://로 시작하고, 알파벳, 어더스코어(_), 하이픈(-), dot(.)으로 이루어져 있는 정규식
http: 로 시작하고,s?: 다음에 s는 없거나, 있고,\/\/: 다음에 특수기호 // 가 오고[\w\-\.]+: \w(영문자, 언더스코어), 하이픈, 쩜 으로 이루어진 문자열이 한개 이상(+) 있다.g: 매칭되는걸 모두 다 찾는다.(플래그)
1
2
3
4
| const text = `http://dogumaster.com http://google.com 010-1111-2222 02-333-7777 curryyou@aaa.com`;
const regExp = /https?:\/\/[\w\-\.]+/g;
text.match(regExp); // ["http://dogumaster.com", "http://google.com"]
|
1
2
3
| const regExp =/([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
const regExp = /^((http(s?))\:\/\/)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/;
const regExp = /^[^((http(s?))\:\/\/)]([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/;
|
자동차 번호판
1
2
| var car = /^[0-9]{2}[\s]*[가-힣]{1}[\s]*[0-9]{4}$/;
var old_car = /^[가-힣]{2}[\s]*[0-9]{2}[\s]*[가-힣]{1}[\s]*[0-9]{4}$/;
|
참고