[데이터] 정규표현식 총정리 (Regular Expression)

Q0. 개요

데이터를 추출할 때, 정해진 포맷으로 편리하게 사용하는 경우를 예로 빗대어 보자.

전화번호는 무조건 010/011/016-XXXX-XXXX와 같은 형태를 가지고 있다.

이러한 패턴으로만 입력할 수 있도록 '패턴을 이용한 데이터 정제'가 정규식이라고 보면 된다.

하지만, 여태까지 정규식에 대해서는 구글링을 해서 나오는 정해진 포맷과 사용 예제를 그대로 복사해서 사용할 뿐 제대로 찾아서 공부를 해본적이 따로 없었다. 그래서 개발 이해도 향상을 목적으로 이번 기회에 정규식에 대해 정리한다.

 

Q1. 정규식이란

문자를 필터링하여 특정 패턴으로 표현하기 위한 규칙이라고 본다.
쉽게 말하면, 문자열을 판독하는 언어 패턴으로 빠르게 검색 및 유효성 체크를 한다.

 

- 주요 용어 정리 (패턴, 메타문자, 문자, 반복자, 그룹)

패턴 : 흔히 정규식 패턴이라고 부르는데, 검색하거나 매칭할 문자열의 구조를 정의.
메타 문자 : 패턴을 정의하는 특수 문자 (예를 들면 ^, $, *, +, ? 등)
문자 클래스 : 대괄호 []안에 있는 문자들 중 하나와 매칭.
반복자 : 패턴의 반복 횟수를 지정하는데 사용되는 메타 문자 (예를 들면, *, +, {n}, {n,}, {n,m} 등)
그룹 : 소괄호 ()를 사용하여 패턴을 그룹화해서 사용. 

 

- 메타 문자 정리

 

- 특수 기호 정리

백슬래시 메타 문자를 사용할 때, 아래의 특수 기호를 제외하고는 모드 이스케이프로 사용된다.

참고로, \b 경계를 나타내는 특수 기호의 예시를 추가 설명한다.

Good \bHello\b의 경우, GoodHello(x) Good Hello(x) Good Hello World(o)
Good \bHello의 경우, GoodHello(x) Good Hello(o) Good Hello World(o)

 

- 문자 클래스에서 사용하는 '메타 문자와 특수 기호' 총 정리

더보기

[] 대괄호안의 문자클래스에서 사용되는 Sets이라는 내용물은 아래와 같이 정리할 수 있다.

구분 내용
1. 단일 문자 - [abc]: "a", "b", "c" 중 하나와 일치
- [^abc]: "a", "b", "c"를 제외한 어떤 문자와도 일치.
2. 범위 - [a-z]: 소문자 알파벳 중 하나와 일치
- [A-Z]: 대문자 알파벳 중 하나와 일치
- [0-9]: 숫자 중 하나와 일치.
3. 조합 - [a-zA-Z]: 소문자 또는 대문자 알파벳 중 하나와 일치.
- [0-9a-fA-F]: 16진수 숫자 중 하나와 일치.
4. 사전 정의된 문자 클래스 - \d: 숫자와 일치 (동일 as [0-9]).
- \D: 숫자가 아닌 문자와 일치 (동일 as [^0-9]).
- \w: 단어 문자 (알파벳, 숫자, 밑줄)와 일치.
- \W: 단어 문자가 아닌 문자와 일치.
- \s: 공백 문자와 일치 (공백, 탭, 개행).
- \S: 공백 문자가 아닌 문자와 일치.
5. 이스케이프 문자 - \\: 역슬래시 문자 자체를 표시.
- \.: 점 (마침표) 문자 자체를 표시.
6. 특수 문자 클래스 - .: 어떤 문자와도 일치 (단, 개행 문자 제외)
- .^: 문자열 또는 행의 시작과 일치
- .$: 문자열 또는 행의 끝과 일치.

위 기본적인 내용을 토대로 정규표현식을 해석하고 작성하면 된다. 마지막으로 이미 사용되는 예제를 확인해보자.

참고로, 여기를 클릭해서 작성 중인 정규표현식을 테스트하기.

- 자주 사용하는 정규표현식의 패턴 목록

더보기
구분 내용 설명
문자 /[a-zA-Z0-9]/ 영문자 대소문자, 숫자로만 구성
/^[a-zA-Z0-9]*$/  공백없는 숫자와 대소문자
/[^?a-zA-Z0-9/]/ 한글포함 특수문자와 공백
/^(?=.*[ㄱ-ㅎㅏ-ㅣ가-힣A-Z!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/ 한글, 대문자, 특수문자, 공백 포함
/[^-가-?a-zA-Z0-9/ ]/ 한글제외 특수문자와 공백
/[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/g 특수문자
/[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"\s]/g 특수문자와 공백 체크
^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$
/[0-9]/g
숫자인지 체크
/\s/g 모든 공백 체크
이메일 /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/ 일반 이메일 주소 체크
/(([^<>()\[\]\\.,:\s@"]+(\.[^<>()\[\]\\.,:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/ 정밀한 이메일 주소 체크
비밀번호 /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$/ 최소 8자리 이상 영문 대소문자, 숫자, 특수문자가 각각 1개 이상
/^(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$ 최소 8자리 이상 숫자, 특수문자가 1개 이상 포함
번호 /^\d[3]-\d[3,4]-\d[4]$/ 3자리-3~4자리-4자리 유형 (문자 아무거나 가능)
/^\d{2,3}-\d{3,4}-\d{4}$/ 일반 전화번호
/^\d{3}-\d{3,4}-\d{4}$/ 휴대폰 번호
/^[-A-Za-z0-9_]+[-A-Za-z0-9_.]*[@]{1}[-A-Za-z0-9_]+[-A-Za-z0-9_.]*[.]{1}[A-Za-z]{1,5}$/ 주민등록번호 체크
시간 /^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/ 년월일 (yyyy-mm-dd) 체크
개발 <a\s+(?:[^>]*)href=\"((?:https:\/\/|http:\/\/)(?:.*?))">(?:.*?)<\/a> 웹사이트 링크인지 체크
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#()?&//=]*)/ URL 체크 (프로토콜 포함)
/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ URL 체크 (프로토콜 옵션)
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ IP 주소 (IPv4)
/^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$/ 맥어드레스 체크
/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/ HTML 태그인지 체크
/(?!<a\sname=\"([\w\s\d\-\.\#]+)\"><\/a>)<a\sname=\"([\w\s\d\-\.\#]+)\">(.*?)<\/a>/ 하이퍼링크 체크
/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
example@gmail.com


/^\d{3}-\d{3,4}-\d{4}$/
010-1111-2222

/^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/
2000-10-30

 

정규표현식을 표현하기 위한 주요 내용들을 정리했다면, 

내가 주로 사용하는 각 언어나 툴에서는 어떻게 적용할지를 확인해보려고 한다.

Q2. 환경에 따라 다른 정규표현식 적용

내가 작업 중인 환경들의 정규표현식을 사용하는 방법에 대해 알아보자.

- JavaScript

1-0. 기본 표현식

 

1-1. 정규식 메소드

1-2. 플래그 옵션

2. 적용 방식 : 리터럴 방식과 생성자 방식 2가지가 존재한다.

 

- Java

java.util.regex 패키지에서 주로 Pattern와 Matcher 클래스를 통해 정규 표현식을 사용한다.

다른 클래스들에 비해 빠른 장점이 있다.

1. Pattern 클래스를 이용한 방법

Pattern pattern = Pattern.compile("^[a-z0-9A-Z]*$"); //표현식이 옳바른지 검증한다.
String patternStr = pattern.pattern(); //옳바른 정규식을 문자열로 반환한다.


String sample = "0123456789";   //정규식 체크할 샘플데이터 생성
boolean result = Pattern.match(patternStr, sample); //샘플데이터를 지정 정규표현식에 일치하는지 체크

String patternStr = pattern.pattern()과 같이 정규표현식을 문자열로 반환하는 역할까지 제공된다.

 

2. Matcher 클래스를 이용한 방법

Pattern pattern = Pattern.compile("^[a-z0-9A-Z]*$"); //표현식이 옳바른지 검증한다.


String sample = "0123456789";   //정규식 체크할 샘플데이터 생성
Match matcher = pattern.matcher(sample); //Pattern객체로 matcher메서드를 이용하여 정규식의 필터링된 결과를 반환한다.


System.out.println(matcher.find()); //matcher객체를 통해, 패턴이 일치하는지를 boolean으로 반환
System.out.println(matcher.group()); //matcher객체를 통해, 매칭된 부분을 반환
System.out.println(matcher.matches()); //matcher객체를 통해, 완벽하게 일치하는지 boolean으로 반환
System.out.println(matcher.start()); //matcher객체를 통해, 매칭되는 문자열의 시작위치 반환
System.out.println(matcher.end()); //matcher객체를 통해, 매칭되는 문자열의 끝위치 반환

String patternStr = pattern.pattern()과 같이 정규표현식을 문자열로 반환하는 역할까지 제공된다.

 

- Oracle

replace함수를 확장한 개념으로 복잡하지만 알아두면 좋은 REGEXP_REPLACE함수를 사용한다.

1. REGEXP_REPLACE  함수 이용한 방법

표현식
REGEXP_REPLACE(source, pattern, replace_string, position, occurrence, match_param)

옵션: 부분 source, pattern, replace_string만 사용도 충분하다
source : 원본 데이터. (char, varchar2-, nchar, nvarchar2, clob, nclob 데이터타입 가능)
pattern: 찾을 정규식 패턴. (char, varchar2, nchar, nvarchar2 데이터타입 가능)
replace_string : 변환할 형태. (패턴에 해당하는 원본 데이터를 변경할 치환 값)
position: 검색 시작 위치. (생략되면 기본값은 1)
occurrence : 패턴과 일치가 발생하는 횟수. (0은 모든 값을 대체. N은 N번째를 대체. 생략되면 기본값은 1)
match_param: 검색 옵션. (c: 대소문자를 구분해서 검색 / i: 대소문자 구분없이 검색 / m: 검색 조건을 여러줄 가능)

예제
REGEXP_REPLACE('ABCDE12345', '([0-9])', '\.-*')는 ABCDE12345라는 문자에서 숫자를 찾아 뒤에 -*를 추가한다. 때문에 ABCDE\.-*\.-*\.-*\.-*\.-*라는 값으로 반환된다.

REGEXP_REPLACE('ABCDE12345', '([0-9])', '\1-*', 'i')는 ABCDE12345라는 문자에서 숫자를 찾아 뒤에 -*를 추가한다. 때문에  ABCDE1-*2-*3-*4-*5-*라는 값으로 반환된다.

 

- SubLimeText3

서브라임 텍스트에서 정규식을 사용하는 방법은 먼저 Ctrl + H 단축키를 통해 Find 창을 연다.

그리고 Find Options섹션에서 '.*' 아이콘을 클릭하여 정규식을 활성화한다.

검색란에 원하는 정규식을 입력하고, Find All 또는 Find를 클릭하여 결과를 표시한다. (검색)FInd에 정규표현식을 입력하고 Replace란에 대체할 내용을 입력하고 Replace All버튼으로 모든 일치 항목 변경 (변경)

 

Q3. 결론

알아두면 정말 좋을 정규표현식을 공부하면서, 외울 필요는 없다는 생각이 들었다.

이미 자주 사용되는 정규표현식 포맷들을 구글링하여 참고할 수 있다보니 외우기보다는 이해하고 해석할 수 있으면 된다.

추가적으로 전체적인 문법과 사용방법에 대해 내가 사용하는 각 언어 별로 정리를 하면서 거리감이 많이 사라진 것 같다.

개인적으로는 에디터에서 원하는 필터로 데이터를 추출하는데 많이 사용할 것 같다.