티스토리 뷰

이 글은 Javascript를 기준으로, 저와같이 정규표현식을 시작하시는 분이 참고가 되도록 작성하였습니다.
MDN의 web docs를 참고하였습니다.(https://mzl.la/2 FbrLTz)

정규표현식(RegExp)

- 문자열에서 특정한 도구를 찾아내는 언어(패턴)입니다.
- JS의 문자열 함수만으로도 가능하나, 정규표현식을 사용하면 문자열에 대한 코드량을 줄일 수 있습니다.
- 처음에는 단순한 문자열 함수에 비해, 표현이 어렵고 사용이 어려우나 익숙해지도록 사용해봅니다.

시작에 앞서 사담을 붙이자면..

정규표현식을 읽고 익히고 사용하는 느낌은 Java의 배열을 배운 상태에서 List를 익힐때의 느낌이라고 하면 와닿을지 모르겠습니다.
배열의 index 또는, for문을 사용하여 배열의 데이터를 다룰 수 있지만
List의 함수를 사용하면 이를 보다 간단하고 효율적이게 할 수 있는 방법도 있습니다.
List의 함수를 알아보고 익힐때의 어색함과 어려움이 정규표현식을 익힐때에 비슷하게 느껴졌습니다.

문자열 로직 작성시 정규표현식 외에 방법으로 할 수 있기에, 다른 블로그나 Docs를 보아도 원래 방법을 쓰면 된다는 생각에 공부를 시작하지 못했던 것 같습니다.

저와 같으신 분들이 한명쯤은 있으실 것 같아 사담을 붙였으며 정규표현식을 배우고 나면 좀 더 효율적으로 문자를 다루실 수 있을겁니다.

정규표현식 효과

정규표현식을 배우기전에 정규표현식을 썼을 때의 효과를 한번 살펴보고자 합니다.
다소 복잡한 문자열 조건이 있다고 생각해 봅시다.
(예 : A문자열에 소문자가 존재하지 않으며, 공백이 존재하지 않고, 글자뒤엔 'ooo'가 꼭 붙어있으며 ....)
위에 조건에 해당하는 문자열 로직을 작성한다고 가정한다면 많은 경우의수를 생각해야 합니다.
여기서 정규표현식을 사용한다면? 로직을 좀 더 간결하고 짧게 구현할 수 있습니다. 
글보단 코드를 직접 보시는게 와닿으실 것 같아 참고가 될만한 페이지를 첨부하였습니다.

참고 : https://sir.kr/pg_lecture/218

정규표현식의 역할

  • 문자 검색
  • 문자 대체
  • 문자 추출

정규표현식 생성

종류 생성자 함수 방식 리터럴 방식
표현식 new RegExp("abc"); /abc/
표현식+플래그 new RegExp("abc","g"); /abc/g
//생성자
var regExp1 = new RegExp("abc");
var regExp2 = new RegExp("abc","g");

//리터럴
var regExp11 = /abc/;
var regExp22 = /abc/g;

정규표현식에서 사용하는 옵션

  • 메서드
  • 플래그
  • 특수문자
  • 속성

메서드

메서드 문법 설명
exec 정규식.exec(문자열) 일치하는 하나의 정보(Array) 반환
test 정규식.test(문자열) 일치 여부(Boolean) 반환
match 문자열.match(정규식) 일치하는 문자열의 배열(Array) 반환
search 문자열.search(정규식) 일치하는 문자열의 인덱스(Number) 반환 (없으면 -1 반환)
replace 문자열.replace(정규식, 대체문자) 일치하는 문자열을 대체하고 대체된 문자열(String) 반환
split 문자열.split(정규식) 일치하는 문자열을 분할하여 배열(Array)로 반환
toString 생성자_정규식.toString() 생성자 함수 방식의 정규식을 리터럴 방식의 문자열(String)로 반환

■ exec : 일치하는 '하나'의 정보(Array) 반환

var pattern = /A/;

console.log( pattern.exec( 'an A' ) );

console.log( pattern.exec( 'Aaa' ) );

console.log( pattern.exec( 'aAa' ) );

console.log( pattern.exec( 'A A Aa A A' ) );

console.log( pattern.exec( 'aba' ) );

exec

■ test : 일치 여부(Boolean) 반환

var pattern = /A/;

console.log( pattern.test( 'an A' ) );

console.log( pattern.test( 'Aaa' ) );

console.log( pattern.test( 'aAa' ) );

console.log( pattern.test( 'A A Aa A A' ) );

console.log( pattern.test( 'aba' ) );

test

■ match : 일치하는 문자열의 배열(Array) 반환

var pattern = /A/;

console.log( 'an A'.match( pattern ) );

console.log( 'Aaa'.match( pattern ) );

console.log( 'aAa'.match( pattern ) );

console.log( 'A A Aa A A'.match( pattern ) );

console.log( 'aba'.match( pattern ) );

match

■ search : 일치하는 문자열의 인덱스(Number) 반환 (없으면 -1 반환)

var pattern = /A/;

console.log( 'an A'.search( pattern ) );

console.log( 'Aaa'.search( pattern ) );

console.log( 'aAa'.search( pattern ) );

console.log( 'A A Aa A A'.search( pattern ) );

console.log( 'aba'.search( pattern ) );

search

■ replace : 일치하는 문자열을 대체하고 대체된 문자열(String) 반환

var pattern = /A/;

console.log( 'an A'.replace( pattern, 'T' ) );

console.log( 'Aaa'.replace( pattern, 'T' ) );

console.log( 'aAa'.replace( pattern, 'T' ) );

console.log( 'A A Aa A A'.replace( pattern, 'T' ) );

console.log( 'aba'.replace( pattern, 'T' ) );

replace

■ split : 일치하는 문자열을 분할하여 배열(Array)로 반환

var pattern = /A/;

console.log( 'an A'.split( pattern ) );

console.log( 'Aaa'.split( pattern ) );

console.log( 'aAa'.split( pattern ) );

console.log( 'A A Aa A A'.split( pattern ) );

console.log( 'aba'.split( pattern ) );

split

■ toString : 생성자 함수 방식의 정규식을 리터럴 방식의 문자열(String)로 반환

var pattern = new RegExp('abcdefg');

console.log(pattern.toString());

toString

JS String Prototype의 함수를 아는 상태에서, 위의 정규표현식을 다루는 메서드는 왜? 어떻게? 써야하는지에 대한 답은 아래 플래그특수문자를 보고 다시 생각하도록 해봅시다.

플래그

플래그 설명
g 전역 검색
i 대소문자 구분 없이 검색
m 문자열의 행이 바뀌더라도 계속 검색
u 유니코드 패턴
y sticky 검색(문자열의 n번째 위치부터 검색)
MDN RegExp.prototype.sticky

■ g : 전역 검색

var str = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.`;

var pattern1 = new RegExp('Lorem','g');
var pattern2 = new RegExp('Lorem');

console.log(str.match(pattern1));
console.log(str.match(pattern2));

input 내용이 길어서 생략(이하 동일)

■ i : 대소문자 구분 없이 검색

var str = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.`;

var pattern1 = new RegExp('lorem','i');
var pattern2 = new RegExp('lorem');

console.log(str.match(pattern1));
console.log('------------------');
console.log(str.match(pattern2));

■ m : 문자열의 행이 바뀌더라도 계속 검색

var noMulti = 'abcdefg';
var multi = 'abcdefg\n' +
            'a'
var noMulReg = /a/; //
var mulReg = /a/gm; //g:모든 문자 m:모든 줄

console.log(noMulti.match(noMulReg));
console.log(multi.match(mulReg));

■ u : 유니코드 패턴

var text = "💩";
console.log(text.length); //가시적으론 1글자이나 2글자(4byte)
console.log(text.charCodeAt(0).toString(16)); //d83d
console.log(text.charCodeAt(1).toString(16)); //dca9
console.log('\ud83d\udca9'); //💩
console.log(text.match(/💩/));
console.log(text.match(/💩/u));

console.log('--------------------------------------------');
var text2 = "a💩b";
console.log(text2.match(/a.b/)); //단일문자가를 찾을때 유니코드를 2글자(d83d,dca9)로 인식하여 null
console.log(text2.match(/a.b/u)); //단일문자를 찾을때 유니코드를 한글자로 적용하여 찾음
console.log(/💩{2}/.test('💩💩')); // 💩{2} : 💩글자가 2개연속 일치
console.log(/💩{2}/u.test('💩💩'));

■ y : sticky 검색(문자열의 n번째 위치부터 검색)

var str = '#foo#';
var regex = /foo/y;

regex.lastIndex = 1;

console.log(regex.test(str)); // true

regex.lastIndex = 5;

console.log(regex.test(str)); // false (lastIndex is taken into account with sticky flag)

console.log(regex.lastIndex); // 0 (reset after match failure)

플래그에 따라 검색결과가 많이 달라지기에 확실하게 익히도록 합니다.

특수문자

특수문자의 경우 양이 방대하여 주관적인 기준으로 기본적으로 알아야 될 부분은 표기하였습니다. (회색음영)

특수문자 설명
^ 줄의 시작에서 일치

예) /^A/ 
"an A"의 A와 일치X
"An E"의 A와 일치O
$ 줄의 끝에서 일치

예) /t$/
"easter"의 t와 일치X
"eat"의 t와 일치O
* 앞의 표현식이 0회 이상 연속으로 반복되는 부분과 일치
{0,} 과 같은 의미

예) /bo*/
"ac booooo efg"의 booooo와 일치O
"ac b efg"의 b와 일치O
+ 앞의 표현식이 1회 이상 연속으로 반복되는 부분과 일치
{1,} 과 같은 의미

예) /bo+/
"ac booooo efg"의 booooo와 일치O
"ac b efg"와 일치X
? 앞의 표현식이 0회 or 1회 등장하는 부분과 일치
{0,1} 과 같은 의미

예) /bo?/
"ac booooo efg"의 bo와 일치O
"ac b efg"의 b와 일치O
?= 긍정형 전방 탐색
패턴검사는 문자열 왼쪽(후방) → 오른쪽(전방)

예) x(?=!) → !로 끝나는 x찾기
"x!" 와 일치O
"xx" 와 일치X
?! 부정형 전방 탐색

예) x(?!!) →!로 끝나지 않는 x찾기
"xx"와 일치O
"x!"와 일치X
. 개행 문자를 제외한 모든 단일문자와 대응

예) /.n/
"nay, an apple is on the tree"의 an과 on 일치O
"nay"와 일치X
{n} n개 연속 일치
{n,} n개 이상 연속 일치
{n,m} n개 이상 m개 이하 (n~m개) 연속 일치
() 캡처할 그룹

예) /(abc)/
"test abc testabctest" 의 하늘색 부분 일치O
\1~9 정규식 내 캡처된 값 참조
/(abc)\1/
[abc] 문자셋
괄호안의 [. ^ *] 같은 문자는 위의 정규표현식의 특수문자로 해석하지 않음

예) /[abc]/
"test abc testabctest" 의 a,b,c,a,b,c 일치O
[^abc] 부정 문자셋
a 또는 b또는 c가 아닌 나머지 문자에 일치

예) /[abc]/
"test abc testabctest" 의 t,e,s,t,t,e,s,t,t,e,s,t 일치O
[\b] 백스페이스에 대응
(\b와 혼동X)
[a-z] a부터 z 사이의 문자 구간에 일치(영어 소문자)
[A-Z] A부터 Z 사이의 문자 구간에 일치(영어 대문자)
[0-9] 0부터 9 사이의 문자 구간에 일치(숫자)
[가-힣] 가부터 힣 사이의 문자 구간에 일치(한글)
[2-7] 2부터 7 사이의 문자 구간에 일치(2,3,4,5,6,7)
[b-f] b부터 f 사이의 문자 구간에 일치(b,c,d,e,f)
\b 63개 문자(영문 대소문자 52개 + 숫자 10개 + _(underscore))가 아닌 나머지 문자에 일치하는 경계(boundary)
\B 63개 문자에 일치하는 경계
\d 숫자(Digit)에 일치
\D 숫자가 아닌 문자에 일치
\s 공백(Space, Tab 등)에 일치
\S 공백이 아닌 문자에 일치
\w 63개 문자(Word, 영문 대소문자 52개 + 숫자 10개 + _)에 일치
[A-Za-z0-9_] 와 동일

\W 63개 문자가 아닌 나머지 문자에 일치
[^A-Za-z0-9_] 와 동일

\u 유니코드(Unicode) 문자에 일치, /\u0061/ a에 일치
\r 캐리지 리턴(CR, U+000D) 문자에 일치
\t 탭 (U+0009) 문자에 일치
a|b a 또는 b와 일치, 인덱스가 작은 것을 우선 반환

 

속성

속성 설명
flags 플래그 반환(String)
정규표현식.flags
global 플래그 g 여부 반환(Boolean)
정규표현식.global
ignoreCase 플래그 i 여부 반환(Boolean)
정규표현식.ignoreCase
multiline 플래그 m 여부 반환(Boolean)
정규표현식.multiline
source 표현식 반환(String)
정규표현식.source
sticky 플래그 s 여부 반환(Boolean)
정규표현식.sticky
unicode 플래그 u 여부 반환(Boolean)
정규표현식.unicode


글을 마치며

여기까지 정규표현식의 기초지식을 한번 살펴보았습니다.
플래그 특수문자는 정규표현식을 사용하기위한 이유이며 MDN을 참고하시면 더 많은 특수문자가 있습니다.
정규표현식을 공부하기위해 인터넷을 검색하면 방대한 양과 어디부터 접근해야할지 고민이 되어 매번 시작을 하지 못하였던 경우가 많아 마음잡고 공부와 동시에 정리해보았으며, 참고가 되시길 바랍니다.

 

정규표현식 연습 사이트 : https://regex101.com
 

Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript

Please wait while the app is loading...

regex101.com

JS Online 사이트 : https://playcode.io/online-javascript-editor
 

Online JavaScript Editor

Online JavaScript Editor - write and run your javascript code online, see live preview in output or in editor console. Share your javascript.

playcode.io

정규표현식 참고 블로그 : https://heropy.blog/2018/10/28/regexp/
 

정규표현식, 이렇게 시작하자!

매일 쓰는 것도, 가독성이 좋은 것도 아니지만, 모르면 안되는 정규표현식. 저는 이렇게 공부하기 시작했습니다! (자바스크립트를 기준으로 설명합니다)

heropy.blog

Thanks to ...
- StomX : '손에 잡히는 정규 표현식' 도서 제공

'Javascript' 카테고리의 다른 글

Promise 패턴  (1) 2019.05.17
댓글