[JavaScript] 자바스크립트 정규표현식 사용법 / 해설
본문 바로가기
겅부합시다

[JavaScript] 자바스크립트 정규표현식 사용법 / 해설

by 쏠수있어ㅤ 2022. 1. 10.
반응형

매번 정규식이 필요할 때마다 구글에서 가져와 쓰다가 이제는 정규식을 좀 알아야겠다 싶어서 공부 겸 정리를 해봅니다.

이 글을 읽는 분들이 한방에 정규식을 쉽게 마스터할 수 있도록 ! 요약해보겠습니다 💁🏻‍♀️

이 글을 읽고 나서는 대략적인 정규 표현식을 이해할 수 있고,

마지막에 안내해드린 테스트 사이트에서 이런 저런 정규식을 만들어 연습하면서 더욱 이해도를 높힐 수 있습니다! 

 

정규 표현식이란 ?  === 정규식

정규 표현식은 원하는 특정 문자 조합을 표현하는 패턴이다. 

'정규식' 이라고 짧게 불리기도 한다.

자바스크립트에서의 정규 표현식은 객체이며 아래의 매서드들과 함께 쓰인다.

RegExp의 exec, test 매서드
String의 match, replace, search, split 매서드

 

정규식 만들기 : 2가지 방법

1. 정규식 리터럴

let regex = /ab+c/;

특징 :

- "/" 슬래쉬로 감싸는 패턴이다. 

- 스크립트가 불러와질 때 컴파일된다. 

- 정규식이 상수라면, 위 방식이 성능을 향상시킬 수 있다. 

 

* 컴파일이란 ?  - 컴퓨터가 이해할 수 있는 언어로 바꾸어주는 과정 

 

2. RegExp 객체의 생성자 함수 호출 

let regex = new RegExp("ab+c");

특징 

- 정규식 실행 시점에 컴파일이 됨

- 정규식 패턴이 변경될 수 있는 경우 or 사용자 입력과 같이 다른 출처로부터 패턴을 가져와야 하는 경우에는 위 방식을 사용

 

 

 

 

 

 

정규식 패턴 작성하기

1. 단순 패턴

단순 패턴 예시 ex.

/abc/

위의 단순 패턴은 표현된 문자열을 그대로 대응시키고자 할 때 사용된다.

문자열에서 정확하게 'abc' 순서까지 모두 일치한다면 대응이 된다.

ex.

"a slabcraft"  ----> abc가 일치하므로 대응됨 

"a crab"  ----> abc가 모두 들어있지만 순서 불일치로 대응이되지 않음

 

 

2. 특수 문자 패턴  

있는 그대로의 패턴 대응이 아닌 공백을 찾거나, 하나 이상의 'a'를 찾거나 등등, 조금 더 복잡한 대응을 필요로 할 경우 특수 문자 패턴이 필요하다. 이 부분이 정규식을 해석할 때 항상 궁금했던 부분이었다 !! 외계어처럼 써져있는 듯한 부분. 

아래 특수문자 리스트를 쭉 훑고 링크걸어놓은 정규식 테스트 웹사이트에서 연습해보면 좋을 것 같다! 

 

특수 문자 패턴 예시 ex) 

/ab*c/

* 의 뜻은 * 바로 앞의 문자가 0개 이상이라는 것을 의미한다. 즉, 위의 패턴은 'a'문자 + 'b'문자 (0개이상) + 'c'문자 순으로 나오는 것과 대응한다. 

ex. "cbbabbbbbbcde" ---- a + b 여러개 + c 이므로 대응된다. 

 

 

정규식 특수문자
특수
문자
의미 예제
\ 1. 특수문자가 아닌 문자 앞에서 사용된 백슬래쉬
: 해당 문자는 특별합니다, 문자 그대로 해석하지 마세요!

2. 특수문자 앞에서 사용된 백슬래쉬
: 해당 특수문자는 특별하지않고 문자 그대로 해석하세요!

=> 쉽게 생각해보면 문자 앞에 \가 있으면 문자자체의 의미가 없어지고 특수문자 앞에 \가 있으면 해당 특수문자의 기능은 사라지고 문자 그대로 해석된다. 

3. RegExp("pattern")표기를 쓰면서 \ 자체를 이스케이프하는 것을 잊지 않기 ! 

* 이스케이프 문자란 ? 
\ 역슬래시 자체를 출력하고 싶을 때 \\ 앞에 역슬래시, 
" 겹따옴표 자체를 출력하고 싶을 때 \" 앞에 역슬래시를 붙여주어야 하는 것 -> \, ", ' 등 \를 써주어야 해당 문자 자체가 출력되는 것들을 이스케이프 문자라고 한다. 
1. 특수문자가 아닌 문자 앞에서 사용된 백슬래쉬 예시
b   : 'b'와 대응
\b  : 어떤 문자와도 대응되지 않음 - 단어 경계 문자 형성


2. 특수문자 앞에서 사용된 백슬래쉬 예시
/a*/    : 0개 이상의 'a'가 등장
/a\*/   : 'a*'와 대응 (*의 기능이 사라짐)


3. RegExp 표기법에서 \ 이스케이프 예시 
/a\*/ 와 같은 패턴을 생성자로 만들려면
new RegExp('a\\*') 이렇게 만들기 !  
- 백슬래쉬 자체를 이스케이브 시켜주기 
^ 입력 시작 부분

만약 다중행 플래그가 참으로 설정되어 있다면, 줄 바꿈 문자 바로 다음 부분과도 대응

만약 ^가 문자셋 ([abc])패턴의 첫 글자로 쓰인다면, 그 때는 전혀 다른 의미를 가진다 --> 역 문자셋 참고
/^A/ 의 경우 

"an A"  : 대응되지 않음
"Apple" : 대응됨 - A로 시작했기 때문
$ 입력의 끝 부분 

만약 다중행 플래그가 참으로 설정되어 있다면, 줄 바꿈 문자 바로 앞 부분과도 대응 
/t$/ 의 경우

"eater"  : 대응되지 않음
"eat" : 대응됨  - t로 끝났기 때문
*
앞의 표현식이 0회 이상 연속으로 반복되는 부분과 대응 
{0,} 과 같은 의미 

/bo*/ 의 경우

"A phost boooooed"  : 대응됨 - b + o 여러번
"A bird warbled" : 대응됨 - b + o 0번
"A goat grunted" : 대응되지 않음 - b or bo 가 없음
+ 앞의 표현식이 1회 이상 연속으로 반복되는 부분과 대응 
{1,} 과 같은 의미 

- * 과 다른 점 : *은 0회 가능, + 는 1회 이상 
/a+/ 의 경우

"candy" : 대응됨 - a가 한개 있다.
"caaaandy" : 대응됨 - a가 여러개 있다.
"circle" 대응되지 않음 - a가 1회도 없으니 안됨!!
? 1. 앞의 표현식이 0 또는 1회 등장하는 부분과 대응
{0, 1} 과 같은 의미

2. 수량자 *, +, ?, {} 바로 뒤에 사용하면, 기본적으로 가능한 한 많이 대응시키는 수량자를 가장 적은 문자들에 대응시킨다. -> 예제 2

3. 또한 ?는 x(?=y) 와 (x(?!y) 항목에서 설명하는 바와 같이 사전 검증을 위해서도 쓰인다.

예제 1.
/e?le?/ 의 경우

"angel"의 "el" 에 대응됨 - 첫번째 e가 1번 + l 
"angle"의 "le" 에 대응됨
"oslo"의 "l"에 대응됨

=> l은 ?의 영향을 받지 않음. 앞뒤의 e만 0개거나 1개인 경우 대응 (le? 요 부분때문에 넘 헷갈렷다....)

예제 2.
/\d+/ 의 경우
"123abc" -> "123" 에 대응됨

/\d+?/ 의 경우
"123abc" -> "1" 에 대응됨

. 개행 문자를 제외한 모든 단일 문자와 대응

* 개행 문자란 ? 
행(줄)을 고치는 문자 / 줄바꿈 문자 / EOL (End-of-line)
/.n/ 의 경우

"nay, an apple is on the ~" : 대응됨 - "an"과 "on"에서 대응됨
*** 첫 개행문자 "nay"에서는 대응되지 않음 

(x) 괄호 안의 x에 대응되고 그것을 기억한다. 

괄호는 포획 괄호 (capturing parentheses)라고 불림 
괄호 안의 x는 문자열이 들어가는 자리 

/ (foo) (bar) \1 \2 / 의 경우

"foo bar foo bar" 에 대응됨 
- 처음의 두 단어에 대응하고 () 괄호 안에 있으므로 이를 기억함.
- \1 \2 은 1번째 , 2번째 포획괄호에 대응된 문자열과 똑같은 문자열에 대응 
(\n 패턴은 앞의 n번째 포획괄호에 대응된 문자열과 똑같은 문자열에 대응) 

* 정규식 치환 부분에서는 $1, $2, $n과 같은 문법이 사용된다. 
ex) 
'bar foo'.replace( /(...) (...)/, '$2 $1') 

(?:x)  x에 대응되지만 대응된 것을 기억하지 않는다. 

괄호는 비포획 괄호 (non-capturing parentheses)라고 불림
/ (?:foo) {1,2} / 의 경우
{1,2}는 'foo' 전체에 적용됨

/ foo {1,2} / 의 경우
{1,2}는 'o'에만 적용됨
x(?=y) 오직 'y'가 뒤따라오는 'x'에만 대응된다. 
이를 lookahead라고 불른다.

/Jack(?=Sprat)/ 의 경우
'Sprat'가 뒤따라오는 'Jack'에만 대응됨

/Jack(?=Sprat | Frost)/ 의 경우
'Sprat' 또는 'Frost'가 뒤따라오는 'Jack'에만 대응됨
그러나 'Sprat'및 'Frost'는 대응 결과의 일부가 아님

x(?!y) 'x'뒤에 'y'가 없는 경우에만 'x'에 일치
이를 negated lookahead라고 불른다.

/\d+(?!\.)/ 의 경우 
소수점이 뒤따라오지 않는 숫자에 일치함

/\d+(?!\.)/.exec("3.141") 을 실해하면
"141"에 일치  ("3.141"은 대응하지않음)

x | y 'x' 또는 'y'에 대응된다. 
/green|red/ 의 경우

"green apple"의 "green"에 대응되고
"red apple"의 "red"에 대응됨

{n} 앞 표현식이 n번 나타나는 부분에 대응
* n은 반드시 양의 정수

/a{2}/ 의 경우

"candy,"의 "a"에 대응되지 않음 (1번이므로)
"caandy," 의 "aa"와 
"caaaaandy," 의 첫 두 "a"에는 대응됨 

{n,m} 앞 표현식이 최소n번 ~ 최대m번 나타나는 부분에 대응
* n, m은 반드시 양의 정수이며 n <= m을 만족해야함 
   m이 생략된다면 무한대(∞)로 취급 

/a{1,3}/ 의 경우

"cndy" 대응되지 않음
"caandy," 첫 두 "aa"와 대응 
"caaaaaaandy" 의 첫 세 "aaa"와 대응

[xyz]
문자셋 (Character set)이다. 

이 패턴 타입은 괄호 안의 어떤 문자 (이스케이프 시퀀스까지 포함)와도 대응된다. 

. 점이나 * 별표같은 특수 문자는 문자셋 내부에서는 특수 문자가 아니므로 이스케이프시킬 필요가 없다. -> 아까 위에서 본 "\"를 사용해서 이스케이프 하는걸  [ ] 안에서는 할 필요가 없다. 

- 하이픈을 이용해 문자의 범위를 지정해줄 수 있다. 

[a-d] 는 [abcd]와 똑같이 동작한다. 
"brisket"의 "b"에 대응하고
"city"의 "c"에 대응됨

/[a-z.]+/ 와 /[\w.\+/ 의 경우
"test.i.ng" 전체 문자열에 대응/일치한다.

* \w는 아래에 👇🏼
[^xyz]
부정 문자셋 (negated character set) 
또는 보충 문자셋 (complemented character set)이다.

[] 괄호 내부에 등장하지 않는 어떤 문자와도 대응된다. 일반적인 문자셋에서 작동하는 모든 것은 부정 문자셋에서도 작동한다.

- 하이픈을 이용해 문자의 범위를 지정해줄 수 있다. 

[^abcd] 는 [^a-d]와 똑같이 동작한다.

"brisket"의 "r", 
"chop."의 "h"에 대응한다.
(abcd를 제외한 모든 것에 대응) 
[\b]
백스페이스 (U+0008)에 대응된다. 
문자 리터럴에 대응시키려면 대괄호 [] 를 이용해야 한다. 
* \b와 혼동 금지!! 

 
\b
단어 경계에 대응된다. 

단어 경계는 다른 '단어 문자'가 앞이나 뒤에 등장하지 않는 위치에 대응된다. 

단어의 경계는 대응 결과에 포함되지 않는다. 
즉, 단어의 경계에 대응되는 문자열의 길이는 항상 0이다. 

* 단어 문자란 ? 
자바스크립트의 정규식 엔진은 특정 문자 집합들이 있다. 
1. 단어 문자 - 로마자 소문자와 대문자, 10진수 숫자, 밑줄 문자로 구성

2. 단어 분리 - 단어 문자가 아닌 모든 문자 
ex)  "é" 또는 "ü"  강세 표시 문자 등 

/\bm/ 의 경우
"moon"의 "m"에 대응됨

/oo\b/ 의 경우 
"moon"의 "oo"에 대응되지 않음 - "oo"뒤에 "n"이라는 단어 문자가 있기 때문에

/oon\b/ 의 경우
"moon"의 "oon"에 대응됨 - "oon"은 문자의 끝이라서 뒤따라오는 단어 문자가 없기 때문에

/\w\b\w/의 경우
어떤 경우에도 일치하지 않음 - 단어 문자는 절대로 비 단어 문자와 단어 문자 두개가 뒤까라올수 없기 때문
\B
단어 경계가 아닌 부분에 대응된다. 아래와 같은 경우들이 있다.

1. 문자열의 첫 번째 문자가 단어 문자가 아닌 경우, 해당 문자의 앞 부분에 대응된다. 

2. 문자열의 마지막 문자가 단어 문자가 아닌 경우, 해당 문자의 뒷 부분에 대응된다.

3. 두 단어 문자의 사이에 대응된다.

4. 단어 문자가 아닌 두 문자 사이에 대응된다.

5. 빈 문자열에 대응된다.

문자열의 시작 부분과 끝 부분은 단어가 아닌 것으로 간주된다.

/\B../ 의 경우
"noonday"의 "oo"과 대응됨

/y\B./ 의 경우
"possibly yesterday."의 "ye"와 대응됨
\cX
문자열 내부의 제어 문자에 대응된다. 
X 는 A ~ Z까지의 문자 중 하나이다. 

/\cM/의 경우 
문자열에서 control-M (U+000D)에 대응됨 
\d
숫자 문자에 대응된다.  [0-9]와 동일하다. 

/\d/ 또는 /[0-9]/ 의 경우
"B2 is the suite number."에서 "2"에 대응됨
\D
숫자 문자가 아닌 문자에 대응된다. [^0-9]와 동일하다. 

/\D/ 또는 /[^0-9]/ 의 경우
"B2 is the suite number." 의 "B"에 대응된다.
\f 폼피드 (U+000C) 문자에 대응된다.
form feed : 프린트 출력 시 현재 페이지를 마친다.
 
\n 줄 바꿈 (U+000A) 문자에 대응된다.
new line : 화면에 출력시 다음 행으로 줄을 바꾼다.
 
\r 캐리지 리턴 (U+000D) 문자에 대응된다.
carriage return : 행의 처음으로 커서를 이동한다.
 
\s
스페이스, 탭, 폼피드, 줄 바꿈 문자 등을 포함한 하나의 공백 문자에 대응된다. 

[ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff ]와 동일하다.
/\S\w*/의 경우

"foo bar." 의 "foo"에 대응됨

\S - foo와 bar 사이의 스페이스에 대응
\w - 영숫자문자 대응
* - 0회 이상 반복 

=>  스페이스 뒤의 "bar"가 대응된다. "."은 \w에 포함되지 않음

\t 탭 (U+0009)문자에 대응된다.  
\v 수직 탭 (U+000B) 문자에 대응된다.  
\w
밑줄 문자를 포함한 영숫자 문자에 대응된다. 
[A-Za-z0-9_] 와 동일하다.

\w에 대응되는 문자를 "단어 문자"라고 한다.

/\w/ 의 경우
"apple," 의 "a"에 대응됨 
"$5.28," 의 "5"에 대응됨
"3D." 의 "3"에 대응됨
\W
\w의 반대 - 단어 문자가 아닌 문자에 대응된다. 
[^A-Za-z0-9_] 와 동일하다. 

/\W/ 의 경우
"50%."의 "%"에 대응됨
\n
정규식 내부의 n번째 괄호에서 대응된 부분에 대한 역참조이다. 
* 여기서의 n은 양의 정수


/apple(,)\sorange\1/ 의 경우
"apple, orange, cherry, peach." 의 "apple, orange,"에 대응함

=> apple - "apple"에 대응
(,) - "," 에 대응 + 컴마를 기억한다. (괄호안에 있는건 기억!)
\s - " " 스페이스에 대응
orange - "orange"에 대응 
\1 - () 괄호 안에 기억한 첫 번째 것 (,)과 대응
모두 합치면 "apple, orange,"가 된다. 

\0
NULL (U+0000)문자에 대응
* 다른 숫자를 뒤에 쓰면 안된다.
왜냐하면 \0<digits>는 8진 이스케이프 시퀀스이기 때문이다.
-> \0 뒤에 숫자를 연이어 쓰면 8진법 이스케이프 라고 여겨진다.

 
\xhh 코드가 hh (두 16진 숫자)인 문자에 일치한다.  
\uhhhh 코드가 hhhh (네개의 16진 숫자)인 문자에 일치한다.  
$& 일치한 전체 문자열을 의미  사용자 입력을 이스케이프해서 정규식 내부에서 문자 그대로 취급해야 하는 경우 간단히 치환을 하면 된다. 

function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

 

 

 

 

 

 

정규식 사용하기

정규식에서 쓰이는 메서드
exec 대응되는 문자열을 찾는 RegExp 매서드

대응되는 문자열을 찾으면 정보를 가지고 있는 배열을 반환
대응되는 문자열을 찾지 못하면 null을 반환
test 대응되는 문자열이 있는지 검사하는 RegExp 매서드

대응되는 문자열을 찾으면 true를, 
그렇지 않으면 false를 반환
match 대응되는 문자열을 찾는 String 매서드

대응되는 문자열을 찾으면 가지고 있는 배열을 반환
찾지 못하면 null을 반환
search 대응되는 문자열이 있는 검사하는 String 매서드

대응된 부분의 인덱스를 반환
찾지 못하면 -1을 반환
replace 대응되는 문자열을 찾아 다른 문자열로 치환하는 String 매서드
split 정규식 혹은 문자열로 대상 문자열을 나누어 배열로 반환하는 String 매서드

 

 

 

 

 

 

이렇게 이론을 공부하고 직접 작성해보고 테스트해보니 그렇게 어려워보였던 정규식이 조금씩 이해가 간다.

요 사이트에서 각각의 정규식이 표현하는 바가 무엇인지 잘 설명해주고 어떤 문자열이 해당 정규식에 포함되는지 나와서 한 눈에 보기 좋다! 

정규식 test website : https://regexr.com/

 

RegExr: Learn, Build, & Test RegEx

RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).

regexr.com

 

References : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions

 

정규 표현식 - JavaScript | MDN

정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.  이 패턴들은 RegExp의 exec 메소드와 test 메소드  ,

developer.mozilla.org

 

 

 

 

반응형

댓글