코테 문제 풀어보기

[ 정규식 ] - 자바 정규식

그냥 케이 2021. 6. 7. 23:09

업무를보다가 정규식을 사용할 일이 많았지만 항상 검색해서 코드만 가져다 쓸 뿐 이렇게 직접 작성은 처음해보는것같다.  개인공부를 하면서 코테 공부도 해보려고 코테에 관련있는 분야부터 시작하게되었다. 

 

일단 기본 문법부터 찾아봤다

 

^ :  시작을 강제해준다.  ex) ^(010)  : 010으로 시작해야함 

& :  종료를 강제해준다  ex) (com)& : com으로 끝나야함 

. : 하나의 문자가 있으면된다 (띄어쓰기 포함 )

[ ] :  특정 문자 포함하는지 체크  ex) [12] : 12345678 중 12를 체크함 

[A-Z] :  - 가 들어가면 범위를 정할수 있다.  ex) [0-9]  : 0~9까지 숫자 하나 들어있으면됨 

[13] :  1 or 3 을 체크한다.

[^1] :  괄호 안에서 ^ 은 not을 의미한다 ,  

\s :  띄어쓰기 , \t  , \n 을 체크한다 

\S : \s에 해당되는것을 제외한 나머지를 체크 

( ) : 문자열을 포함한다  ex) (010) : 010 있는지 체크

(a|b) : a or b 체크  

+ : 1회 이상 반복을 의미 

* : 0회 이상 반복을 의미  + 냐 * 이냐 에따라 결과가 달라질수있다.

? : 있을수도있고 없을수도있다.

{} : 조건에 일치하는 자리수를 체크한다

(?=) : 전방탐색 ,  맨앞부터 검사를 하며 = 다음에오는 일치하는 양식을 조건에서 제외한다 (?=[0-9]{4}) ex) 핸드폰번호 뒷자리 찾을때 

(?<=) : 후방탐색 , 뒤부터 검사하여 = 다음에오는 일치하는 약식을 조건에서 제외한다 (?<=[0-9]{3}) ex) 핸드폰번호 앞자리 찾을때 

==================== 추가

 

(?:aa) : aa 가 들어갈수도있고 다른게 들어갈수도있지만 aa형태를 1번이상 가지고있는것을 찾는다 

(?i) : 대소문자 무시 

\b :  문자와 공백 사이 의미하며 , 아래 예시처럼 앞뒤로 감싸고있으면 특정 word와 정확하게 일치해야만 찾음

만약 아래 처럼 뒤에 \b를 삭제하면 정확하게 일치하지않아도 해당 문자를 찾기는함

 

테스트 코드 

 

 String result = "The cat sat on the mat.12#";
 System.out.println(result.replaceAll("[Tt]he", "*"));  // T or t 이고 뒤에 he 인 모든 텍스트 치환 * The,the
 System.out.println(result.replaceAll("[T]he","*")); // T 이고 뒤는 he인 첫 텍스트 치환 * The
 System.out.println(result.replaceAll("\\s", "*")); //\t \n \x0b \r \f 를 * 치환
 System.out.println(result.replaceAll("\\S","*")); //\t \n \x0b \r \f 를 제외한 문자 * 치환 
 System.out.println(result.replaceAll("\\b", "*")); // 단어 경계 찾아 치환
 System.out.println(result.replaceAll("[1]", "*")); // 문자중 1 있는경우 일치하는것만 치환
 System.out.println(result.replaceAll("[12]", "*")); // 문자중 1 or 2 or 12 일치하는것만 치환
 System.out.println(result.replaceAll("[13]", "*")); // 문자중 1 or 3 or 13 일치하는것만 치환 
 System.out.println(result.replaceAll("[1-3]", "*")); // 문자중 1 or 2 or 3 일치한느것 치환 
 System.out.println(result.replaceAll("[^1]", "*")); // 문자중 1을 제외한 모든 문자 치환
 System.out.println(result.replaceAll("[^1-3]", "*")); // 문자중  1 or 2 or 3  제외한 모든 문자 치환
 System.out.println(result.replaceAll("(The|the)", "*"));   // The or the 이면 치환
 System.out.println(result.replaceAll("(on)+", "*"));   // on 이 1번이상 반복되면 치환
 System.out.println(result.replaceAll("(on)*", "*"));   // on 이 0번이상 반복되면 치환 
 System.out.println(result.replaceAll("[2]$", "*"));      // 맨마지막문자가 2라서 치환 안됨 
 System.out.println(result.replaceAll("[#]$", "*"));   // 맨 마지막 문자가 # 이면 치환
 System.out.println(result.replaceAll("1#$", "*"));   // 맨 마지막 문자가 1# 이라서 치환 안됨 
 System.out.println(result.replaceAll("2#$", "*"));   // 맨 마지막 문자가 2# 이면 치환

 

 

결과

 

 

URL 체크 코드

 

String[] inputs = {"www.naver.com", "http://naver.com","https://naver.com","http://www.naver.com","naver.com/web","naver.com/web/","naver"};
 String reg = "^((http|https)://)?(www.)?[a-zA-Z0-9]+\\.[a-zA-Z]+(/[a-zA-Z0-9]*)?[^/]";

 //String reg = "^((http|https)://)?(www.)?[a-zA-Z0-9]+.[a-zA-Z]+(/[a-zA-Z0-9]*)?[^/]";
for(String input: inputs) {

 if(Pattern.matches(reg, input)) {
 System.out.println("urlCheck :  "+input +"  = "+true);
 }else {
 System.out.println("urlCheck :  "+input +"  = "+false);
 }
}

 

^((http|https)://)?(www.)?[a-zA-Z0-9]+.[a-zA-Z]+(/[a-zA-Z0-9]*)?[^/] 을 하나하나 말로 풀어보자

 

^: 맨앞이

(http|https)://)?     :  http 이거나 https  이고 :// 을 일수도있고 아닐수도있다

(www.)?              :  위에 문장이거나 www. 일수도있고 아닐수도있다 

 

이 문장을통해 앞에올수있는 문자는 아무문자가 안오거나 , http:// or https:// or www.  네가지종류이다 

 

[a-zA-Z0-9]+.        :  영소,영대,숫자가 1번이상 반복해야한다, 마지막은 . 이다

[a-zA-Z]               :  영소,영대,1번이상 반복해야한다,

(/[a-zA-Z0-9]*)?     :   / 와 함께 영소,영대,숫자가 1번이상 반복할수도있고 안할 수도있다.

[^/]                    :  마지막은 /  가 올수없다. 

 

 

1."^((http|https)://)?(www.)?[a-zA-Z0-9]+.[a-zA-Z]+(/[a-zA-Z0-9]*)?[^/]";

2."^((http|https)://)?(www.)?[a-zA-Z0-9]+\\.[a-zA-Z]+(/[a-zA-Z0-9]*)?[^/]";

 

 

1번과 2번에 따라 마지막 결과가 다르게 나온다 

 

 

.에 의미를 알아보기 다시 테스트

@Test
void dotCheck() {
String[] inputs = {".","a.",".b",".."};
 String reg = "\\..";
for(String input: inputs) {

 if(Pattern.matches(reg, input)) {
 System.out.println("dotCheck :  "+input +"  = "+true);
 }else {
 System.out.println("dotCheck :  "+input +"  = "+false);
 }
}
}

결과를 보니 \\. : 텍스트 . 의미하고 뒤에 . 는 정규식에서 사용하는 . 으로  아무문자나 올수잇는  판단된다.

 

그러므로 1번의 + 와 . 이 합쳐저서 naver 라는 텍스트가 정상으로 판단하고 

2번은 \\. 이 텍스트 .을 의미해서 false 로 처리한것으로 생각된다. 

 

 

 

이메일 주소 체크 코드

 

@Test
public void emailCheck() {
String[] inputs = {"kkkk@ai.com", "kkkk@naver.com","kkk@naver.com"
,"k1k1kk1k1k1k1k1@naver.com","k123.com","kadmin@kadmin@naver.com"};
String reg="";

for(String input: inputs) {

 if(Pattern.matches(reg, input)) {
 System.out.println("emailCheck :  "+input +"  = "+true);
 }else {
 System.out.println("emailCheck :  "+input +"  = "+false);
 }
}
}

 

 

^[a-zA-Z0-9]{4,10}@[a-zA-Z0-9]{5,10}\\.[a-zA-Z]+ 을 해석해보면 

// ^ ==> 시작 표시
// [a-zA-Z0-9]{4,10}  영소,영대,숫자 인 텍스트가 4~10자리 이여야한다 \\w 로 대체가능 
// @  ==> "@" 텍스트 포함
// [a-zA-Z0-9]{5,10} 영소,영대,숫자 인 텍스트가 4~10자리 이여야한다   \\w 로 대체가능 
// \\.  ==>  "." 텍스트 포함
//[a-zA-Z]+  영소,영대 문자가 1회이상 반복되야한다

 

 

 

휴대전화 번호 체크 코드  

 

@Test
public void phoneCheck() {



String[] inputs = {"01012345678", "0111234-5678","016-1234-5678"
,"017-123-4567","019-123-456","010-12-4567"};
String reg = "^(010|011|016|017|019)-[0-9]{3,4}-[0-9]{4}";
//String reg1 = "^0(0|1)(0|1|6|7|9)-[0-9]{3,4}-[0-9]{4}";


for(String input: inputs) {

 if(Pattern.matches(reg, input)) {
 System.out.println("phoneCheck :  "+input +"  = "+true);
 }else {
 System.out.println("phoneCheck :  "+input +"  = "+false);
 }
}
}

 

 

^(010|011|016|017|019)-[0-9]{3,4}-[0-9]{4} 해석해보면

^(010|011|016|017|019) : 폰의 앞자리는 010,011,016,017,019 , 그리고 3자리 이다
-                              : 첫번째 자리와 두번째 자리 사이에 - 붙는다 
[0-9]{3,4}                    :  두번째자리는 숫자로만되고 3~4 글자 이다 
-                              : 두번째 자리와 세번째 자리 사이에 - 붙는다
[0-9]{4}                      : 세번째 자리는 수자로만 되고 4 글자 이다

 

 

 

특정 문자 * 처리 

일하다보면 개인정보 때문에 특정 문자를 * 치환할 일이 발생한다. 

1. 번호 마지막 4자리 제외 * 처리

@Test
public void regMethod() {
String[] inputs = {"01012345678", "0101234567","010-1234-5678","010-123-4567"};
for(String input: inputs) {
if(input.indexOf("-")==-1) {
String reg=".(?=[0-9]{4})";
System.out.println("regMethod :  "+input.replaceAll(reg, "*"));
}else {
String reg=".(?=[0-9\\-]{4})";
System.out.println("regMethod :  "+input.replaceAll(reg, "^"));
}
}
}

 

 

2. 이메일 주소 2번째 3번째 문자 * 처리 

원래는 정규식만써서 해보고싶엇는데.. 포기 ......

 

처리순서는 

1. 띄어쓰기 제거

2. @를 포함하는 문자있는지 체크

3. string to char[] 

4. char[2]과 char[3] 값이 [a-z0-9] 포함될때 * 로 치환 후 string에 붙인다.

5. 4번에 해당안될경우 치환안하고 그냥 붙는다 

 

@Test
public void regMethod2() {
String[] inputs = {"kkk k@ai.com", "kkk k@naver.com","k kk@naver.com"
,"k1k1kk1 k1k1k1k1@naver.com","k123.com","kadmin@kadmin@naver.com"};

for(String input: inputs) {
input=input.replaceAll("\s", "");
String reg = ".*\\@.*";
if(Pattern.matches(reg, input)) {
 reg = "[a-z0-9]";
char [] cArray = input.toCharArray();
input="";
for(int i=0;i< cArray.length;i++) {

if(i==2|| i==3) {
input+=Character.toString(cArray[i]).replaceAll(reg,"*");
}else {
input+=Character.toString(cArray[i]);
}
}
System.out.println("regMethod2 :  "+input);
}
}
}