[Java] 정규표현식(Regular Expression)에 대한 정리 본문
[Java] 정규표현식(Regular Expression)에 대한 정리
- 2022. 1. 10. 10:13
정규 표현식(Reqular Expression)은 문자열을 처리하는 방법 중의 하나로 특정한 조건의 문자를 검색하거나 치환하는 과정을 매우 간편하게 처리할 수 있도록 하는 수단이다.
이메일이나 전화번호 등 특정 문자열을 확인할 때 if문과 for문을 통해 지저분하게 처리하던 것을 정규 표현식을 활용하면 훨씬 간단하고 깔끔하게 처리할 수 있다.
Java에서는 util.regex 패키지에서 제공하는 Pattern과 Matcher 라이브러리를 사용하여 정규 표현식을 활용할 수 있다.
실제로 문자열 클래스인 String 클래스는 특정한 조건의 문자를 검색하거나 치환하는 메서드를 정규 표현식을 활용하여 구현하였다.
대표적으로 matches, replaceAll, replace, split 메서드들이 있다.
정규표현식은 쓸 때마다 헷갈려서.. 매번 검색하는 것도 성가시니 이번 기회에 정리를 하고 넘어가야겠다.
정규표현식 정리
표현식 | 설명 |
^ | 문자열의 시작 |
$ | 문자열의 종료 |
. | 임의의 한 문자 (문자의 종류 가리지 않음, 단, \ 는 넣을 수 없음) |
* | 앞 문자가 없을 수도 무한정 많을 수도 있음 |
+ | 앞 문자가 하나 이상 |
? | 앞 문자가 없거나 하나있음 |
[] | 문자의 집합이나 범위를 나타내며 두 문자 사이는 - 기호로 범위를 나타낸다. []내에서 ^가 선행하여 존재하면 not 을 나타낸다. |
{} | 횟수 또는 범위를 나타낸다. |
() | 소괄호 안의 문자를 하나의 문자로 인식 |
| | 패턴 안에서 or 연산을 수행할 때 사용 |
\s | 공백 문자 |
\S | 공백 문자가 아닌 나머지 문자 |
\w | 알파벳이나 숫자 |
\W | 알파벳이나 숫자를 제외한 문자 |
\d | 숫자 [0-9]와 동일 |
\D | 숫자를 제외한 모든 문자 |
\ | 정규표현식 역슬래시(\)는 확장 문자. 역슬래시 다음에 일반 문자가 오면 특수문자로 취급하고 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미 |
(?i) | 앞 부분에 (?i) 라는 옵션을 넣어주면 대소문자를 구분하지 않음 |
자주 쓰이는 정규식 패턴
분류 | 정규식 패턴 |
숫자 | ^[0-9]*$ |
영문자 | ^[a-zA-Z]*$ |
한글 | ^[가-힣]*$ |
영어&숫자 | ^[a-zA-Z0-9]*$ |
비밀번호 (숫자, 문자 포함의 6~12자리 이내) | ^[A-Za-z0-9]{6,12}$ |
비밀번호 (숫자, 문자, 특수문자 포함 8~15자리 이내) | ^.*(?=^.{8,15}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$ |
이메일 | ^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$ |
휴대전화 | ^\\d{3}-\\d{3,4}-\\d{4}$ |
일반전화 | ^\\d{2,3}-\\d{3,4}-\\d{4}$ |
주민등록번호 | \d{6} \- [1-4]\d{6} |
파일확장자 | ^\\S+.(?i)(txt|pdf|hwp|xls)$ |
이중 파일확장자 | (.+?)((\\.tar)?\\.gz)$ |
정규식 사용 예제
1. 숫자만
1
2
3
4
5
6
7
8
9
10
|
String str = "123456a";
Pattern pattern = Pattern.compile("^[0-9]*$");
Matcher matcher = pattern.matcher(str);
if(matcher.find()) {
System.out.println(Integer.parseInt(str));
} else {
System.out.println("숫자가 아닌 값이 포함되어 있습니다. ");
}
|
cs |
2. 이메일 형식
1
2
3
4
5
6
7
|
String pattern2 = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$";
String str2 = "abc_123@gmail.com";
if(Pattern.matches(pattern2, str2)) {
System.out.println("올바른 이메일 형식입니다. ");
} else {
System.out.println("올바른 이메일 형식이 아닙니다. ");
}
|
cs |
3. 휴대전화 형식
1
2
3
4
5
6
7
|
pattern2 = "^\\d{3}-\\d{3,4}-\\d{4}$";
str2 = "010-1234-1234";
if(Pattern.matches(pattern2, str2)) {
System.out.println("올바른 휴대전화 형식입니다. ");
} else {
System.out.println("올바른 휴대전화 형식이 아닙니다. ");
}
|
cs |
4. 파일 확장자 형식
1
2
3
4
5
6
7
8
9
10
11
|
pattern2 = "^\\S+.(?i)(txt|pdf|hwp|xls)$";
str2 = "abc.txt";
// 이중확장자
// pattern2 = "(.+?)((\\.tar)?\\.gz)$";
// str2= "lib.tar.gz";
if(Pattern.matches(pattern2, str2)) {
System.out.println("올바른 확장자 형식입니다. ");
} else {
System.out.println("올바른 확장자 형식이 아닙니다. ");
}
|
cs |
패턴 분석: ^\S+.(?i)(txt|pdf|hwp|xls)$
^ : 시작
\ : \ 가 왔기 때문에 다음에 올 문자는 특수문자로 취급하고 , \다음 특수문자고 오면 그 자체로 취급.
\S : 공백 아닌 문자
+. : .이 반드시 한개는 와야한다.
(?i) : 대소문자 구별하지 않음.
(txt|pdf|hwp|xls) : txt 혹은 pdf 혹은 hwp 혹은 xls 만 허용. | 을 이용한 or 연산!
$ : 끝
-> 공백아닌 문자와 .이 반드시 와야하고 뒤에는 txt, pdf, hwp, xls 만 허용.
아래는 추가적으로 사용한 예시이다.
1. 이름 마스킹
// 이름 가운데 글자 마스킹
public static String nameMasking(String name) throws Exception {
// 한글만 (영어, 숫자 포함 이름은 제외)
String regex = "(^[가-힣]+)$";
Matcher matcher = Pattern.compile(regex).matcher(name);
if(matcher.find()) {
int length = name.length();
String middleMask = "";
if(length > 2) {
middleMask = name.substring(1, length - 1);
} else { // 이름이 외자
middleMask = name.substring(1, length);
}
String dot = "";
for(int i = 0; i<middleMask.length(); i++) {
dot += "*";
}
if(length > 2) {
return name.substring(0, 1)
+ middleMask.replace(middleMask, dot)
+ name.substring(length-1, length);
} else { // 이름이 외자 마스킹 리턴
return name.substring(0, 1)
+ middleMask.replace(middleMask, dot);
}
}
return name;
}
이름 마스킹은 지난번 포스팅의 로직에서 한글 정규식 패턴만 가져올 수 있게 변경하였습니다.
마찬가지로 2글자 이상의 이름은 가운데 글자 마스킹. 외자는 끝자리만 마스킹.
2. 휴대폰번호 마스킹
// 휴대폰번호 마스킹(가운데 숫자 4자리 마스킹)
public static String phoneMasking(String phoneNo) throws Exception {
String regex = "(\\d{2,3})-?(\\d{3,4})-?(\\d{4})$";
Matcher matcher = Pattern.compile(regex).matcher(phoneNo);
if(matcher.find()) {
String target = matcher.group(2);
int length = target.length();
char[] c = new char[length];
Arrays.fill(c, '*');
return phoneNo.replace(target, String.valueOf(c));
}
return phoneNo;
}
휴대폰번호 마스킹은 가운데 숫자 4자리 마스킹이고, '-'(하이픈)이 들어오나 안들어오나, 숫자 길이와 형식이 맞으면 마스킹 처리가 됩니다.
3. 이메일 마스킹
// 이메일 마스킹(앞3자리 이후 '@'전까지 마스킹)
public static String emailMasking(String email) throws Exception {
String regex = "\\b(\\s+)+@(\\s+.\\s+)";
Matcher matcher = Pattern.compile(regex).matcher(email);
if(matcher.find()) {
String target = matcher.group(1);
int length = target.length();
if(length > 3) {
char[] c = new char[length - 3];
Arrays.fill(c, '*');
return email.replace(target, target.substring(0, 3) + String.valueOf(c));
}
}
return email;
}
이메일 마스킹은 앞3자리 제외, @전까지 마스킹 처리입니다. 이메일 형식이 올바르다면 마스킹 처리가 됩니다.
4. 계좌번호 마스킹
// 계좌번호 마스킹(뒤 5자리)
public static String accountNoMasking(String accountNo) throws Exception {
// 계좌번호는 숫자만 파악하므로
String regex = "(^[0-9]+)$";
Matcher matcher = Pattern.compile(regex).matcher(accountNo);
if(matcher.find()) {
int length = accountNo.length();
if(length > 5) {
char[] c = new char[5];
Arrays.fill(c, '*');
return accountNo.replace(accountNo, accountNo.substring(0, length-5) + String.valueOf(c));
}
}
return accountNo;
}
계좌번호 마스킹은 뒷 5자리 숫자를 마스킹 처리하고, 정규식 패턴에 상관없이 숫자 형식 패턴으로 이뤄져 있다면 상관없이 마스킹 처리가 됩니다.
계좌번호는 각 은행마다 자릿수가 다 틀려서 숫자 패턴만 이용했습니다.
5. 생년월일 마스킹
// 생년월일 마스킹(8자리)
public static String birthMasking(String birthday) throws Exception {
String regex = "^((19|20)\\d\\d)?([-/.])?(0[1-9]|1[012])([-/.])?(0[1-9]|[12][0-9]|3[01])$";
Matcher matcher = Pattern.compile(regex).matcher(birthday);
if(matcher.find()) {
return birthday.replace("[0-9]", "*");
}
return birthday;
}
생년월일 마스킹은 숫자 모두 마스킹 처리이고, '-'(하이픈), '.'(점)이 들어오나 안들어오나 생년월일 8자리 형식이 올바르다면 마스킹 처리 됩니다.
6. 카드번호 마스킹
// 카드번호 가운데 8자리 마스킹
public static String cardMasking(String cardNo) throws Exception {
// 카드번호 16자리 또는 15자리 '-'포함/미포함 상관없음
String regex = "(\\d{4})-?(\\d{4})-?(\\d{4})-?(\\d{3,4})$";
Matcher matcher = Pattern.compile(regex).matcher(cardNo);
if(matcher.find()) {
String target = matcher.group(2) + matcher.group(3);
int length = target.length();
char[] c = new char[length];
Arrays.fill(c, '*');
return cardNo.replace(target, String.valueOf(c));
}
return cardNo;
}
카드번호 마스킹은 가운데 8자리 숫자 마스킹 처리이고, 마찬가지로 '-'(하이픈)이 포함된 카드 번호 숫자 형식이 올바르다면 마스킹 처리가 됩니다.
7. 주소 마스킹
// 주소 마스킹(신주소, 구주소, 도로명 주소 숫자만 전부 마스킹)
public static String addressMasking(String address) throws Exception {
// 신(구)주소, 도로명 주소
String regex = "(([가-힣]+(\\d{1,5}|\\d{1,5}(,|.)\\d{1,5}|)+(읍|면|동|가|리))(^구|)((\\d{1,5}(~|-)\\d{1,5}|\\d{1,5})(가|리|)|))([ ](산(\\d{1,5}(~|-)\\d{1,5}|\\d{1,5}))|)|";
String newRegx = "(([가-힣]|(\\d{1,5}(~|-)\\d{1,5})|\\d{1,5})+(로|길))";
Matcher matcher = Pattern.compile(regex).matcher(address);
Matcher newMatcher = Pattern.compile(newRegx).matcher(address);
if(matcher.find()) {
return address.replaceAll("[0-9]", "*");
} else if(newMatcher.find()) {
return address.replaceAll("[0-9]", "*");
}
return address;
}
'프로그램 > JAVA' 카테고리의 다른 글
Restful Api 호출 하는 샘플2 입니다. (0) | 2022.04.04 |
---|---|
Restful Api 호출 하는 샘플1 입니다. (0) | 2022.04.04 |
크롬에서 Talend API Tester 사용하기 (0) | 2021.05.26 |
Spring WebSocket 소개 (0) | 2021.03.02 |
pom.xml에서 Failed to transfer 501 에러 발생시 (0) | 2021.02.26 |
RECENT COMMENT