티스토리 뷰
문제 링크
programmers.co.kr/learn/courses/30/lessons/72410?language=javascript#
자바스크립트 연습 겸 프로그래머스 레벨 1 문제들을 풀어보고 있습니다.
이 문제를 C++로 풀 때는 몰랐는데 막상 풀어보니 정규표현식에 입문하기 너무 좋은 문제입니다. 이리저리 검색해보면서 정규표현식이 되게 친숙해졌습니다. 이게 복잡해 보여서 그렇지 정규식 생각보다 어렵지 않습니다..
우선 전체적인 코드는 이렇습니다.
function solution(new_id) {
return new_id
.toLowerCase()
.replace(/[^\w-.]/g, '')
.replace(/\.+/g, '.')
.replace(/^\.|\.$/g, '')
.replace(/^$/g, 'a')
.substr(0, 15).replace(/\.$/g, '')
.replace(/^(.)$/, '$1$1$1')
.replace(/^(.)(.)$/, '$1$2$2');
}
한 단계씩 살펴보기
1) 모든 대문자를 소문자로 치환
new_id.toLowerCase()
내장 함수를 이용하면 쉽게 할 수 있습니다.
2) 알파벳 소문자, 숫자, 빼기, 밑줄, 마침표를 제외한 모든 문자를 제거
new_id.replace(/[^\w-.]/g, '')
정규표현식의 리터럴은 슬래시 사이에 원하는 표현식을 넣고, 끝에 플래그를 달아서 사용하면 됩니다.
플래그를 사용하지 않으면 처음으로 패턴과 일치하는 문자열을 찾고 종료하는데, g 플래그를 이용하면 패턴과 매칭 되는 모든 문자열을 찾아줍니다.
대괄호([])는 문자셋(Character Set)입니다. 대괄호 내에 사용한 모든 문자 중 매칭 되는 문자를 찾습니다. 하이픈(-)을 이용해 연속한 문자를 나타낼 수 있습니다.
예를 들어 대문자는 A-Z, 소문자는 a-z, 한글은 가-힣, 숫자는 0-9와 같이 사용합니다.
\w는 모든 영문자, 숫자, 밑줄(_)에 대응됩니다. 즉, /\w/는 /[A-Za-z0-9_]/와 동일합니다.
문자셋 내에서는 정규 표현식에서 특별한 기능을 하는 특수 문자를 일반 문자처럼 처리합니다. 따라서 아래에서 나올 \. 과 같은 이스케이프 처리를 해주지 않아도 됩니다.
문자셋의 처음에 ^를 붙여주면 이를 부정 문자셋(Negated Character Set)이라고 부릅니다.
부정 문자셋은 문자셋과 반대로 문자셋에 대응되는 문자를 제외한 모든 문자에 대해 대응됩니다.
위 코드를 해석하면 "영어 대소문자, 숫자, 밑줄(_), 빼기(-), 마침표(.)를 제외한 모든 문자를 찾아서 빈 문자열('')로 replace 해라."가 되겠습니다.
3) 연속된 마침표를 하나로 치환
new_id.replace(/\.+/g, '.')
정규표현식에서 마침표(.)는 특별한 기능을 하는 문자이기 때문에, 마침표 자체를 문자로써 매칭 시키려면 백 슬래시(\)를 이용해 마침표를 이스케이프 시켜줘야 합니다.
문자의 뒤에 +를 사용하면, 이는 그 문자가 한 번 이상 나왔는지에 대한 패턴을 뜻합니다.
위 코드를 해석하면 "마침표(.)가 한 번 이상 연속해서 나온 문자열을 '.'으로 replace 해라."가 되겠습니다.
4) 양 끝의 마침표를 제거
new_id.replace(/^\.|\.$/g, '')
^X는 문자열의 가장 앞 문자가 X와 매칭 되는지 검사합니다. 헷갈리면 안 됩니다. 이는 문자셋에서 사용된 ^와는 다른 의미입니다.
X$는 문자열의 가장 뒷 문자가 X와 매칭되는지 검사합니다.
|는 일반적으로 코딩할 때 사용하는 |와 비슷한 의미입니다. '또는'으로 해석하시면 되겠습니다.
위 코드를 해석하면 "가장 처음에 나온 마침표(.)와, 가장 뒤에 나온 마침표(.)를 빈 문자열('')로 replace 해라."가 되겠습니다.
|가 or의 의미인데 왜 코드를 해석하면 and 같은 의미가 되죠?? → 패턴에 대한 or이기 때문에 A | B 라면 A 또는 B와 대응되는 모든 문자열을 찾아준다고 생각하시면 됩니다.
5) 빈 문자열이라면, 'a'를 대입
new_id.replace(/^$/g, 'a')
^와 $는 4번에서 설명했습니다.
시작 문자와 끝 문자에 대응되는 문자를 써주지 않았기 때문에, 이는 곧 빈 문자열을 의미합니다.
위 코드를 해석하면 "new_id가 빈 문자열과 매칭 되면 'a'로 replace해라."가 되겠습니다.
6) 첫 15개의 문자만 남기고, 맨 뒤의 마침표를 제거
new_id.substr(0, 15).replace(/\.$/g, '')
자바스크립트의 substr() 함수는 시작 위치와 개수를 인자로 받습니다. 처음부터 15개의 문자만 뽑은 뒤, 4번과 같은 방식으로 맨 뒤의 마침표를 제거해줍시다.
7) 길이를 3으로 만들기
new_id.replace(/^(.)$/, '$1$1$1')
.replace(/^(.)(.)$/, '$1$2$2');
정규표현식에서 소괄호(())는 캡쳐링 그룹(Capturing Group)이라고 합니다. 대응되는 패턴이 있을 때, 각 캡쳐링 그룹 순서대로 해당 문자열을 기억해둡니다.
이렇게 기억한 문자열을 순서대로 $1, $2, ..., $9와 같이 접근할 수 있습니다. (다만 $을 이용해 접근하는 방식은 비표준 구문이라고 합니다. 자세한 내용은 두 번째 참고사이트를 참고해주세요.)
마침표(.)는 어떤 문자와도 대응될 수 있습니다.
따라서 위 코드를 해석하면 "문자가 하나일 땐 첫 번째 문자($1)가 세 번('$1$1$1') 나오도록, 문자가 두 개일 땐 두 번째 문자($2)가 한 번 더 나오도록('$1$2$2') replace 해라."가 되겠습니다.
참고 링크
'개발 > Javascript' 카테고리의 다른 글
[Javascript] Array.prototype.map()의 콜백 내에서 사용되는 this (0) | 2021.06.23 |
---|