정규 표현식 (Regular Expression) 과 응용 사례를 정리해 보자
정규표현식은 특정한 조건으로 문자를 검색하거나 바꿀 때 사용하는데요.
사용은 하지만, 자주 사용하지는 않아서,
정작 사용할 때가 되서는, 기억이 가물가물한 경우가 많습니다.
오늘은 자주 쓰이는 것들을 위주로, 정규 표현식과 응용 사례(이메일 형식체크 등)들을 정리해 보겠습니다.
1. 정규 표현식
아래는 자주 사용되는 정규식을 정리해 놓은 표입니다.
주의할 것은 "\"(역슬래쉬)는 Kotlin이나 Java에서는 Escape문자로,
코드에서 사용할 때는 "\\"(역슬래쉬 2개) 로 대신 표기해 주어야 합니다.
( ) | 패턴들을 하나의 그룹으로 묶음 예> or연산자인 | 과 함께 써서, (txt|hwp|doc) 과 같이 txt, hwp,doc 세가지에 매치시킬 수 있음 |
+ | 기호 앞의 패턴이 1번 이상 발생하는 패턴 예> ^\S+ (공백없는 텍스트로 시작하고, 한글자이상의 길이로 됨) |
? | 기호 앞의 패턴이 없거나 1번 발생하는 패턴 (0~1번 발생) 예> \d+ (숫자가 없가나 1번 발생하는 패턴) |
* | 기호 앞의 패턴이 없거나 1번 이상발생하는 패턴 (0 ~ 1번 이상 발생, ?과 *를 구분해야 함) |
. | 모든 문자를 가르킴(\과 개행은 제외) ex> ab. 이라면 abx이건, ab3이건 모두 포함된다. |
^ | 문자열(패턴)이나 행의 처음을 의미 |
$ | 문자열(패턴)이나 행의 종료 |
[ ] | [ ]사이에 들어간 문자중 하나를 매치 예> [abc] 는 ab, ac, ac를 모두 포함 |
[^ ] | [ ] 의 부정을 의미. 예> [^0-9] 라면, 0에서 9를 포함하지 않은 문자를 의미 |
[A-Z] | A에서 Z까지의 대문자 중 하나를 찾습니다. [0-9]는 0부터 9까지를 의미 |
\b | 단어와 단어간의 사이 ex> welcome to my world 라면, "\bto\b" 로 to를 매칭해 낼 수 있습니다. |
\s | 공백문자 (스페이스) |
\S | 공백을 제외한 나머지 문자들 (공백이 없는 텍스트 일때 사용하게됩니다) |
\w | "_"를 포함한, 영어와 숫자들 |
\W | "_"를 제외한, 영어와 숫자가 아닌 문자열들과 일치. |
\d | 숫자를 일치 시킨다. [0-9]와 동일 |
\D | 숫자가 아닌 모든 문자 |
{M,N} | 최소 M번 이상, 최대 N번 이하로 발생하는 패턴 참고로, {}는 정확하게 몇번 발생하는지를 말합니다. 예> \d{6} \- [1-4]\d{6} (주민등록 번호의 경우6자리숫자와 대쉬(-), 그리고 1에서4부터 숫자 + 6자리 숫자로 구성됩니다) |
| | or연산을 의미 (txt|doc) 는 txt또는 doc를 의미한다. |
(?i) | 대소문자를 구분하지 않음 |
광고
1-1. 모든 숫자, 영문자
추가적으로 자주 사용하게 되는, 모든 숫자, 영문자는 아래와 같이 표현할 수 있습니다.
- [a-zA-Z] : 모든 영문자,a-z는 소문자를 의미하구요, A-Z는 대문자를 의미합니다.
- [0-9] : 0-9까지의 모든 숫자 ('\d')와 동일
- [a-zA-Z0-9] : 대문자 및 소문자의 영문자와 숫자
1-2. 횟수나 양을 정의
횟수나 양을 정의할 때는 아래의 표현식을 사용해주면 됩니다.
정규식 | 의미 |
{M} | M회 이상을 반복 |
{M, N} | 최소 M번 이상, 최대 N번 이하로 발생하는 패턴 참고로, {}는 정확하게 몇번 발생하는지를 말합니다. 예> \d{6} \- [1-4]\d{6} (주민등록 번호의 경우6자리숫자와 대쉬(-), 그리고 1에서4부터 숫자 + 6자리 숫자로 구성됩니다) |
* | 0회 이상을 반복 |
+ | 1회 이상을 반복 |
? | 0 또는 1회만 |
*? | 가장 적게 일치하는 것을 찾기 |
광고
예를 들어서, 바코드 번호처럼 몇회이상 반복되는 숫자를 찾는다고 하겠습니다.
그럼 아래처럼, \d로 숫자를 찾고 그것을 3회이상 반복하도록 합니다.
- 숫자연속 6개이상 : \d{6,}
문자도 해 볼수 있겠지요. 아래와 같이 쉽게 가능합니다.
- 문자연속 6개이상 : \w{6,}
1-3. 그루핑
그룹은 "( )"로 지정할 수 있습니다.
아래는 Kotlin공식문서에 나와있는 예제인데요.
()으로 문자와 숫자의 각각의 그룹패턴을 가지고 Regex()객체를 만들어서,
find함수로 이용해 주었습니다.
2. 정규표현식 응용 사례
2-1. 숫자만 나오도록 할 때
텍스트는 제거하고 숫자만 나오도록 하고자 할 때가 있는데요.
replaceAll이라는 메소드와 정규 표현식을 사용할 수 있습니다.
>> string.replaceAll("[^0-9]","");
[^0-9]는 숫자가 아닌 것을 의미하여서, 숫자가 아닌 모든 것을 ""으로 대체하라는 것인데요.
""은 결국 제거하는 것이 됩니다.
참고로 Kotlin에서는 replaceAll()함수가 없는데요. 대신 첫번째 인자에 .toRegex()함수를 체이닝해서 넣어주면 됩니다.
아래와 같이 숫자만 나오도록 하여습니다.
2-2. 이메일 형식 체크
@와 .com 들어간 이메일 주소를 확인할 때 사용합니다.
>> regex = "[0-9a-zA-Z][_0-9a-zA-Z-]*@[_0-9a-zA-Z-]+(\\.[_0-9a-zA-Z-]+){1,2}$";
- @(at마크)다음에 .com같이 .(점) 이 들어가야 하는데요.
.(점)은 정규 표현식에서 모든 문자를 가르켜서, escape를 해주어야 합니다.
""안에 넣었기 때문에 \\으로 escape합니다.
실제로 helloWorld@tistory.com이라는 이메일과 helloNot이라는 텍스트를 가지고,
match()메소드를 이용해서 테스트를 해보겠습니다.
아래와 같이 첫번째 텍스트만 true값을 반환해 준 것을 볼 수 있습니다.
2-3. 파일 확장자 확인
- regex = "^\\S+.(?i)(txt|pdf|hwp|xls)$";
true를 반환하는 것을 확인할 수 있습니다.
2-4. 기타 자주 사용되는 정규식 들
기타 실제 자주 사용되는 정규식 패턴들은 다음과 같습니다.
구분 | 정규식 |
휴대폰 번호 | \d{3}-\d{3,4}-\d{4} |
전화번호 | /^\d{2,3}-\d{3,4}-\d{4}$/ |
패스워드 10자리이상, 대문자, 숫자, 특수문자 포함 |
(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{10,} |
날짜체크 (yyyy-mm-dd) |
(19|20|21|22|23)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01]) |
신용카드번호 | [0-9]{4}[-\s\.]?[0-9]{4}[-\s\.]?[0-9]{4}[-\s\.]?[0-9]{4} |
3. 참고 사이트
정규 표현식에 어느정도 익숙해 지면,
실제로 정규표현식들을 만들어보고 테스트 해봐야 할텐데요.
아래 사이트에서 실제로 표현식을 만들고 테스트 해볼수 있습니다.
4. 팁 및 주의할 점
4-1. 개행단위로 분리하기 (replace)
많은 줄의 문장이 있다고 가정해 보겠습니다.
이 때, 각줄의 문장의 단어들을 사용하려고 한다면, 가장 먼저 할 것은,
개행을 분리해서 리스트에 담아내는 것 입니다.
시스템마다, \r\n 혹은 \r 또는 \n 을 사용하고 있으므로,
아래와 같이 해주면 됩니다.
val splitResults = text.split("\r\n", "\r", "\n", "\n\r")