개발일지/Front-end

정규표현식(Regular Expression) 정복하기 (with Frontend Javascript) 1

cotnmin 2023. 2. 26. 23:59

프론트엔드에서도 입력자의 값을 검증하거나 API를 통해 가져온 값을 분석 또는 재구성해서 사용하고 싶을 때 정규표현식을 이용할 수 있다.

정규표현식(Regular Expression)이란?

특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다.
프로그래밍을 하는 과정에서 문자열을 검증하거나 문자열 일부를 추출하고 싶을 때 많이 사용한다.

Javascript에서 정규식 사용하기

일단 Javascript에서는 정규식 리터럴이나 RegExp 객체를 이용해 정규표현식을 선언할 수 있다.
생성된 정규식은 문자열이 아닌 정규식 객체이다.

const regexp1 = /a\d{1,}/i;
const regexp2 = new RegExp(/a\d{1,}/, 'i');
const regexp3 = new RegExp('a\\d{1,}', 'i');
// 'a' 또는 'A' 뒤에 숫자가 1개 이상 나열 되는지 체크

위 3가지 모두 같은 정규식을 의미한다.
하드코딩이 가능한 부분은 1번의 방식으로 사용자 입력에 따르거나 API통신을 통해 정규식을 생성해야 하는 경우는 3번의 경우를 주로 쓰게 된다.
이미 생성된 정규식에서 플래그만 다른 새 정규식이 필요한 경우 2번 같이 사용 가능

위 정규식을 하나씩 해석하면

  1. / a \d{1,}/i : 문자 'a'
  2. /a \d {1,}/i : 모든 숫자
  3. /a\d {1,} /i : {n, m} n개 이상 m개 미만 -> 1개 이상
  4. /a\d{1,}/ i : 대소문자 구분 X -> 1번의 문자 'a', 'A'둘 다 가능

==> 'a' 또는 'A' 뒤에 숫자가 1개 이상 나열 되는지 체크

위와 같이 해석이 가능합니다 그럼 자세히 알아보겠습니다.

정규식 구문

Groups and Ranges (그룹과 범위)

정규식에서 일부를 그룹으로 묶을 필요가 있을 때 사용
추후 match 라는 메서드와 주로 사용

 

구문 해석 예시
[abc] a 또는 b 또는 c /[012]/: 0, 1, 2 중 하나
[a-z] a 에서 z 중 하나 /[ㄱ-ㅎㅏ-ㅣ가-힣]/: 한글과 매치
[^a-z] a 에서 z 제외 /[^0-9]/: 숫제 제외
a | b a 또는 b [ab]와 유사
(abc) Capturing group /(abc)/: '012abcd'에서 'abc'를 그룹화하고 캡쳐링 ($1, $2 등으로 사용 가능)
(?<name>abc) Named capturing group /(?<name>abc)/: '012abcd'에서 'abc'를 그룹화하고 name으로 캡쳐링 함
(?:abc) Non-capturing group /(?:abc)/: '012abcd'에서 'abc'를 그룹화하고 캡쳐링 하지 않음
\n (\1, \2, \3 ...) n번 째 캡쳐된 그룹 재사용 /(ab)(c)\2\1/: 'abccabb'에서 'abccab'와 매치됨

Character classes (문자 클래스)

키보드로 입력하기 힘들거나 문자를 하나씩 입력하면 너무 길어질 수 있는 부분을 짧게 대체해서 사용하기 위해서 사용

구문 해석 예시
. 모든 문자
* \n(개행문자) 제외
/.a/: a 앞에 아무문자 존재 (a로 시작 X) 단, /\./이나 /[.]/.과 매치
\d 모든 숫자 /[0-9]/과 동일
\D 모든 숫자 제외 /[^0-9]/과 동일
\w 모든 알파벳, 숫자, 언더바 /[A-Za-z0-9_]/과 동일
\W 모든 알파벳, 숫자, 언더바 제외 /[^A-Za-z0-9_]/과 동일
\s 모든 single white space /[\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/과 동일
\S 모든 single white space 제외 /[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/과 동일
\t
\n \r
tab
line feed
carriage return
 

Assertions (어서션)

문자에 매칭하는 것이 아닌 앞뒤 상황에 따라 매칭, 어서션은 매칭 결과에 포함되지 않는다.

구문 해석 예시
^~ ~로 시작 /^abc/: 'abcd'의 abc와 매칭 '1abc'와 매칭 X
~$ ~로 끝 /xyz$/: 'vwxyz'의 abc와 매칭 'xyz012'와 매칭 X
\b 단어의 경계 매치 /\babc\b/: '0 abc d', 'abc d'의 abc와 매칭 '0abc'와 매칭 X
\B 단어의 경계 제외 /\Babc/: '0abc'의 abc와 매칭, 'a abc'의 'abc'와 매칭 X
x(?=y) 뒤에 y가 있을 경우 /xx(?=y)/: 'xxyz'의 'xx'와 매칭 'xxzy'와 매칭 X
x(?!y) 뒤에 y가 없을 경우 /xx(?!y)/: 'xxxy'의 'xx'와 매칭(앞 2개) 'xxyz'와 매칭 X
(?<=y)x 앞에 y가 있을 경우 /(?<=y)xx/: 'yxx'의 'xx'와 매칭 'vxx'와 매칭 X
(?<!y)x 앞에 y가 없을 경우 /(?<!y)xx/: 'vxx'의 'xx'와 매칭 'zxx'와 매칭 X

Quantifiers (수량자)

앞 문자를 반복해서 사용할지 결정

구문 해석 예시
{n} n번 반복 /abc{2}/: 'abccccccc'의 'abcc'와 매칭
{n,} n번 이상 반복 /abc{2,}/: 'abccccccc'의 'abccccccc'와 매칭
{n,m} n번 이상 m번 미만 반복 /abc{2,4}/: 'abccccccc'의 'abcccc'와 매칭
? 0 또는 1 ({0,1} 과 동일) /x?yz/: 'xxxyz'의 'xyz'와 매칭, 'vyz'의 'yz' 와 매칭
* 0개 이상 ({0,} 과 동일) /x*yz/: 'xxxyz'의 'xxxyz'와 매칭, 'vyz'의 'yz' 와 매칭
+ 1개 이상 ({1,} 과 동일) /x+yz/: 'xxxyz'의 'xxxyz'와 매칭, 'vyz'와 매칭 X

기본적으로 수량자는 탐욕적(Greedy)으로 동작하는데, 이는 매치되는 부분을 찾고도 더 길게 찾을 수 있으면 그걸 찾는 걸 말한다.
이때 ?를 뒤에 붙이면 탐욕적으로 찾는 것을 멈춘다. (x??,x{1,5}?)

Greedy: '<div>test</div>'.match(/<.*>/)[0] => <div>test</div>

Non-greedy: '<div>test</div>'.match(/<.*?>/)[0] => <div>

Flag (플래그)

Flag MDN설명 상세 설명
g 전역 탐색. 첫번째 매치결과 외 다른 모든 결과를 매치
i 대소문자를 구분하지 않음. A나 a를 구분하지않음
d 부분 문자열 일치에 대해 인덱스 생성. match나, exec 결과에 indices가 추가된다.
s 개행 문자가 .과 일치함. 문자 클래스 중 .이 \n도 포함
m 여러 줄에 걸쳐 탐색. 기본적으로 첫줄 외의 문자열은 탐색 X, 다만 이걸 켜면 \n으로 여려줄이 되어도 전부 탐색
u "unicode" 패턴을 유니코드 코드 포인트의 시퀀스로 간주함. \u{unicode}다음같은 방식으로 유니코드를 매치할 수 있다. \u{61} == 'a'
y "접착" 탐색, 대상 문자열의 현재 위치에서 탐색을 시작함. 한번 탐색 후 다음 탐색은 마지막 위치에서 다시 시작 (아래에 자세히 설명)
// y Flag
const regex = /test/y;
const str = 'testtesttest!';
regex.test(str);
// 첫번째 탐색 (testtesttest!) // true
regex.test(str);
// 두번째 탐색 (testtest!) // true
regex.test(str);
// 세번째 탐색 (test!) // true
regex.test(str);
// 네번째 탐색 (!) // false

1번에서는 정규식을 해석하고 작성하는 방법을 적었다면
2번에서는 Javascript에서 정규식을 활용하는 string method 또는 regexp method를 적을 예정이다.

 

해석이 어려운 정규식이 있다면 https://regexr.com/ 와 같은 페이지들을 활용할 수 있다.

 

참고