문제가 너무 길어 다 가져오지는 않겠지만 요약하면 이렇다. 3자 이상 15자 이하의 String을 입력하였을 때, 주어진 조건에 맞추어 바꾸는 문제였다. 조건은 이렇다.
1. 모든 대문자를 대응되는 소문자로 치환합니다.
2. 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3. 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4. 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5. 빈 문자열이라면, "a"를 대입합니다.
6. 길이가 16자 이상이면, 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7. 길이가 2자 이하라면, 마지막 문자를 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
다른 단계는 toLowerCase(), length(), substring(), charAt() 메서드를 쓰면 쉽게 풀렸으나 2, 3, 4단계를 구현할 때는 새로 배운 것이 있어 기록을 남겨놓으려 한다.
2단계
replaceAll() 메서드를 쓰면 될 것 같은데 내가 정규식에 익숙하지 않아 이번 기회에 정규식을 공부해보기로 했다.
정규표현식의 공부
정규표현식(Regular Expression)이란 문자열 데이터 중에서 원하는 조건(패턴)과 일치하는 문자열 부분을 찾아내기 위해 사용하는 것으로, 미리 정의된 기호와 문자를 이용해서 작성한 문자열을 말한다. 자주 쓰이는 패턴의 정규식을 보면서 분석하면서 공부를 해보았다.
* 숫자의 정규식
^[0-9]*$ → ["0에서 9까지 중 하나"가 0번 이상 발생]으로 시작하고 끝나는 것.
* 영문자의 정규식
^[a-zA-Z]*$ → ["a-z까지,A-Z까지중의 하나"가 0번 이상 발생]으로 시작하고 끝나는 것.
* 한글의 정규식
^[가-힣]*$ → ["가-힣까지 중의 하나"가 0번 이상 발생]으로 시작하고 끝나는 것.
* 이메일의 정규식
\\w+@\\w+\\.\\w+(\\.\\w+)?
여기서부터 막히기 시작했다. \w는 알파벳 대소문자+숫자+"_" 라고 나와 있는데, 앞에 백슬래시가 하나 더 있다. 백슬래시에 대한 내용을 구글링해보았다.
자바에서는 백슬래시가 등장하면 바로 다음 문자를 인식하여 상황에 맞게 처리하는데, 이를 이스케이프 시퀀스(Escape Sequence)라고 한다.
예를 들어 \n을 입력하면 줄바꿈, \t은 탭, \'은 ', \"은 " 으로 출력되는 것이다.
그래서 백슬래시 자체를 표현하려면?
// 만약 String에 가나\다라 이라는 값을 넣고 싶다고 하자.
String str = "가나\다라";
System.out.println( str );
// 위 코드를 실행하면 java: illegal escape character 오류가 난다.
// 출력코드에서 오류가 나는 것이 아니라 선언부의 줄에서 오류가 난다.
// 애초에 대입시킬 때부터 잘못 넣었다는 뜻이다.
String str = "가나\\다라";
System.out.println( str );
// 위 코드를 실행하면 가나\다라 으로 출력이 된다.
위 코드에서 봤듯이, 백슬래시를 표현하려면 \\로 표현해야 되어서 이메일 가장 앞에 \\w가 나오는 것이다.
일단은 백슬래시 다음에 일반 문자가 오면 특수 문자 형태가 되고(ex. \n), 백슬래시 다음에 특수 문자가 오면 그 문자 자체가 된다고 이해하면 좋을 것 같다!
다시 아까의 이메일의 정규식을 보면서 분석해보자.
- \w = 알파벳 대소문자+숫자+"_" ==> 정규식에서 백슬래시를 나타내려면 \\로 써야 한다.
- \\w+ : 알파벳 대소문자+숫자+"_"가 한개 이상 발생
- @
- \\w+ : 알파벳대소문자+숫자+"_"가 한 개 이상 발생
- \\. : 온점 : 역슬래시 다음에 특수 문자가 오면 그 문자 자체로 취급한다.
- \\w+ : 알파벳대소문자+숫자+"_"가 한 개 이상 발생
- (\\.\\w+)? : "온점+\w가 최대 한 개 이상 발생"이 없거나 최대 한 개 있거나.
- ex. a_b1@a_b1.a_b1.a_b1
- ex. a_b1@a_b1.a_b1
문제에서 주어진 조건을 정규식으로 만들어 보자.
알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자
알파벳 소문자, 숫자, 빼기, 밑줄, 마침표 → a-z0-9-_\\.
마침표는 정규식에서 임의의 문자 1개를 의미하므로 일단 따로 \\처리하여 특수기호임을 명시해놓는다.
이를 모두 제외한 문자 → [^a-z0-9-_\\.]
str.replaceAll( "[^a-z0-9-_\\.]", "" );
3단계
온점이 연속된 부분을 하나로 줄이면 된다. 하나 이상 발생했음을 나타내는 기호 +를 이용하여 정규식을 짜면 된다.
str.replaceAll( "\\.+", "." );
4단계
사실 이 단계는 정규식을 쓰는 단계는 아니었는데 이 단계에서 오류가 났으므로 기록해놓는다. 이 단계에 마침표가 처음이나 끝에 위치한다면 제거를 해주면 되는데 코드를 아래 코드처럼 썼다가 오류가 났다.
if ( answer.charAt( 0 ) == '.' ) {
answer = answer.substring( 1 );
}
if ( answer.charAt( answer.length() - 1 ) == '.' ) {
answer = answer.substring( 0, answer.length() - 1 );
}
만약 answer의 길이가 0인경우 answer.charAt(-1)이 되어 오류가 난 것 같았다. answer.length()>=1의 조건을 추가해주어 해결해주었다. length() 메서드를 이런 식으로 쓸 때 유념할 것!
if ( answer.length() >= 1 && answer.charAt( answer.length() - 1 ) == '.' ) {
answer = answer.substring( 0, answer.length() - 1 );
}
항상 프로그래머스 문제를 풀고 다른 사람의 코드리뷰를 하다보면 정규식을 잘 이용해서 푼 케이스가 종종 보였다. 그 때마다 찾아보기는 했는데 그래도 보기가 좀 어려워서 의미만 대강 이해하고 넘어갔던 기억이 있다. 오늘 정규식을 분석해보고 공부해보니 다음 코드 리뷰 때 정규식이 나오면 좀 더 잘 이해할 수 있을 것 같다. 그리고 나중에 정규식 문제가 나오면 더 익숙하게 쓸 수 있을 것 같다!
참고한 사이트 링크 정리
자바 정규식 사용법 정리[Java] 정규표현식 사용법 및 예제
자바 이스케이프 문자(escape sequence) 정리
자바 특수문자, 괄호, 백슬래시, 따옴표 출력하기
'STUDY > JAVA' 카테고리의 다른 글
[TIL] 실무에서 Stream은 어떻게 쓰이고 있을까? (0) | 2023.05.30 |
---|---|
[TIL] 추상클래스와 인터페이스의 차이. (0) | 2023.05.30 |
[TIL] 다형성 코드로 익혀보기 (0) | 2023.05.27 |
[TIL] 프로그래머스 - 완주하지 못한 선수 (0) | 2023.05.26 |
[TIL] 프로그래머스 - 체육복 (0) | 2023.05.23 |