본문 바로가기
Programming/자바스크립트

[자바스크립트] 정규 표현식

by 코딩하는 랄로 2023. 10. 28.
728x90

정규 표현식

정규 표현식(정규식 : Regular Expression)은 문자열에서 특정 내용을 찾거나 대체 또는 발췌하는데 사용된다. 대표젹으로 입력칸에 전화번호나 이메일을 입력하라고 했을 때 옳지 않은 값을 입력하면 정규표현식에 의해 필터링되어 걸러져 경고창의 띄우는 것이 이에 해당한다.

 

정규표현식을 사용하면, 복잡한 양식을 검사해야하는 일도 반복문과 조건문 등 복잡한 코드없이 간단한 코드로 작성이 가능하다. 주로 다음과 같은 상황에서 사용된다.

 

  • 각각 다른 포맷으로 저장된 전화번호 데이터를 추출해야 할 때
  • 사용자가 입력한 이메일, 휴대폰 번호 등이 올바른지 검증하고 싶을 때
  • 코드에서 특정 변수의 이름을 치환하고 싶지만, 해당 변수의 이름을 포함하고 있는 함수는 제외하고 싶을 때
  • 특정 조건과 위치에 따라서 문자열에 포함된 공백, 특수문자를 제거하고 싶을 때

 

 

 

정규식 생성

정규식은 자바스크립트에 RegExp 객체를 통해 생성할 수도 있지만, 리터럴 방식으로도 생성할 수 있다. 리터럴 방식을 사용할 경우, 슬래쉬 문자 두개를 통해 정규식을 생성한다.

// 리터럴 방식
const regex = /abc/;

// 생성자 방식
const regex = new RegExp("abc");
const regex = new RegExp(/abc/); // 이렇게 해도 됨

 

 

 

정규식 메소드

RegExp 객체에는 아래의 두가지 메소드를 가진다.

메소드 설명
RegExp.test(문자열) 문자열이 정규식과 매칭되면 true, 아니면 false
RegExp.exec(문자열) 첫번째로 매칭되는 매칭 결과만 반환

 

정규 표현식 메소드의 사용예제이다. exec 메소드의 경우 매칭되는 결과가 없으면 null은 반환한다.

// 정규표현식을 담은 변수
const regex = /apple/; // apple 이라는 단어가 있는지 필터링

// "문자열"이 "정규표현식"과 매칭되면 true, 아니면 false반환
let rst = regex.test("Hello banana and apple"); // true
console.log(rst)

rst = regex.exec("Hello banana and apple apple")
console.log(rst)
/* 첫번째 매칭되는 apple에 대한 결과만 반환
[
  'apple',
  index: 17,
  input: 'Hello banana and apple apple',
  groups: undefined
]
*/

 

 

 

정규식을 사용하는 문자열 메소드

문자열의 메소드에서도 정규식을 위한 메소드도 있고, 정규식 사용을 허용하는 메소드도 있다.

메소드 설명
String.match(/정규식/플래그) 문자열에서 정규식에 매칭되는 항목들을 배열로 반환
String.replace(/정규식/, 대체문자열) 정규식에 매칭되는 문자열을 대체문자열로 변환
String.split(/정규식/) 정규식을 기준으로 문자열을 쪼개서 배열로 반환
String.search(/정규식/) 정규식에 매칭되는 문자열의 index를 반환

 

위의 메소드들은 immutation 메소드이기 때문에 원본의 문자열이 변경되지 않는다. (replace도 새로운 문자열을 반환하는 것!!)

// 정규표현식을 담은 변수
const regex = /java/; // java 이라는 단어가 있는지 필터링

// match
// "문자열"에서 "정규표현식"에 매칭되는 항목들을 배열로 반환
// 없으면 null 반환
const txt = "Hello java and javascript";
let rst = txt.match(regex);
console.log(rst);
/*
[
  'java',
  index: 6,
  input: 'Hello java and javascript',
  groups: undefined
]
*/

//replace
// "정규표현식"에 매칭되는 항목을 "대체문자열"로 변환
rst = txt.replace(regex, "html"); // Hello html and javascript
console.log(rst)


// "정규표현식"에 매칭되는 문자열의 인덱스를 반환
// 없으면 -1을 반환
rst = txt.search(regex)
console.log(rst)   // 6

 

 

 

정규식 플래그

정규식 플래그는 정규식을 생성할 때 검색을 위한 옵션을 설정할 수 있도록 지원하는 기능이다. 옵션으로는 아래와 같고 여러개를 동시에 설정해주는 것도 가능하다.

플래그 의미 설명
i ignore case 대소문자를 구별하지 않고 검색
g global 문자열 내의 모든 패턴을 검색
m multi line 문자열의 행이 바뀌더라도 검색
s \n  
u unicode 유니코드 전체를 지원
y sticky 문자 내 특정 위치에서 검색을 진행하는 sticky 모드 활성화

 

플래그를 설정하기 위해서는 리터럴 방식에서는 /정규식/ 뒤에 플래그 문자열을 넣어주어야 하고, 생성자 방식에서는 두번째 파라미터로 플래그 문자열을 넘겨주면 된다.

// flags 에 플래그 문자열이 들어간다.
const flags = 'i';
const regex = new RegExp('abapplec', flags);

// 리터럴로 슬래쉬 문자뒤에 바로 표현이 가능
const regex1 = /apple/i;
const regex2 = /apple/gm;

 

아래는 플래그 중에서 자주 사용되는 i, g, m 에 대한 예제이다.

// i
// ignore case : 대소문자가 달라도 같은 문자로 취급
let str = 'Hello Java';

let rst = str.replace(/java/, 'javascript');
console.log(rst);  // Hello Java

rst = str.replace(/java/i, 'javascript');
console.log(rst);  // Hello javascript


// g
// 문자열 내의 모든 패턴을 검색
str = 'hello java and java';

rst = str.replace(/java/, 'javascript');
console.log(rst);  // hello javascript and java <= 하나만 바뀜

rst = str.replace(/java/g, 'javascript');
console.log(rst);  // hello javascript and javascript


// m
// 입력 시작(^) 앵커나 입력 종료($) 앵커는 각 줄별로 대응되게 만들어졌기 때문에,
// 여러줄을 검색해야 할 때는 m을 사용해야 검색 가능
// 문자열의 행이 바뀌더라도 검색을 계속
str = "hello \n java"

rst = str.match(/^java/); //null
console.log(rst);  // 

rst = str.match(/java/m);
console.log(rst);  // [ 'java', index: 8, input: 'hello \n java', groups: undefined ]

 

위에서 언급하였듯이 플래그는 중첩하여 사용할 수 있다.

let str = 'Hello Java, jaVa, JAVA, jAvA';

let rst = str.replace(/java/ig, 'JS');
console.log(rst);  // Hello JS, JS, JS, JS

 

 

 

정규식 기호

정규식을 잘 사용하기 위해서는 정규식을 표현하기 위한 기호와 기호가 무엇을 의미하는지 알고 있어야 한다.

 

특정 문자, 숫자 매칭 기호

기호 의미
a-zA-Z 영어알파벳(-으로 범위 지정)
ㄱ-ㅎ가-힣 한글 문자(-으로 범위 지정)
0-9 숫자(-으로 범위 지정)
. 모든 문자열(숫자, 한글, 영어, 특수기호, 공백 모두)
단, 줄바꿈 X
\d 숫자
\D 숫자가 아닌 것
\w 밑줄 문자를 포함한 영숫자 문자에 대응
[A-Za-z0-9_] 와 동일
\W \w 가 아닌 것
\s space 공백
\S space 공백이 아닌 것
\특수기호 특수기호 \* \^ \& \! \? ...등
\b 63개 문자(영문 대소문자 52개 + 숫자 10개 + _(underscore))가 아닌 나머지 문자에 일치하는 경계(boundary)
\B 63개 문자에 일치하는 경계
\x 16진수 문자에 일치
/\x61/는 a에 일치
\0 8진수 문자에 일치
/\141/은 a에 일치
\u 유니코드(Unicode) 문자에 일치
/\u0061/는 a에 일치
\c 제어(Control) 문자에 일치
\f 폼 피드(FF, U+000C) 문자에 일치
\n 줄 바꿈(LF, U+000A) 문자에 일치
\r 캐리지 리턴(CR, U+000D) 문자에 일치
\t 탭 (U+0009) 문자에 일치

 

정규식 검색 기준 기호

기호 의미
| OR
a|b
[] 괄호안의 문자들 중 하나. or 처리 묶음 보면 된다.
/abc/ : "abc"를 포함하는
/[abc]/ : "a" 또는 "b" 또는 "c" 를 포함하는
[다-바] : 다 or 라 or 마 or 바
[^문자] 괄호안의 문자를 제외한 것
[^lgEn] "l" "g" "E" "N" 4개 문자를 제외

※ 대괄호 안에서 쓰면 제외의 뜻, 대괄호 밖에서 쓰면 시작점 뜻
^문자열 특정 문자열로 시작 (시작점)
/^www/
문자열$ 특정 문자열로 끝남 (종착점)
/com$/

 

정규식 갯수 반복 기호

기호 의미
? 없거나 or 최대 한개만
/apple?/
* 없거나 or 있거나 (여러개)
/apple*/
+ 최소 한개 or 여러개
/apple+/
*? 없거나, 있거나 and 없거나, 최대한개 : 없음
{0}와 동일
+? 최소한개, 있거나 and 없거나, 최대한개 : 한개
{1}와 동일
{n} n개
{Min,} 최소 Min개 이상
{Min, Max} 최소 Min개 이상, 최대 Max개 이하
{3,5}? == {3}와 동일

 

정규식 그룹 기호

기호 의미
() 그룹화 및 캡쳐
(?: 패턴) 그룹화 (캡쳐 X)
(?=) 앞쪽 일치(Lookahead),
/ab(?=c)/
(?!) 부정 앞쪽 일치(Negative Lookahead),
/ab(?!c)/
(?<=) 뒤쪽 일치(Lookbehind),
/(?<=ab)c/ 
(?<!) 부정 뒤쪽 일치(Negative Lookbehind),
/(?<!ab)c/

 

 

 

정규식 그룹 패턴

정규식 그룹 기호를 사용한 정규식 그룹 패턴은 정규식에서 어려운 난이도에 속한다. 정규식의 그룹 패턴에 대해서 조금 더 알아보자.

 

정규식의 그룹화는 특정 문자열의 나열을 하나의 그룹으로 묶어서 사용하고 싶을 때 사용하는 것이다. 아래의 예제를 살펴보자.

let str = 'jsssss jsssss';

let rst = str.match(/js+/);
console.log(rst);  // [ 'jsssss', index: 0, input: 'jsssss jsssss', groups: undefined ]

 

js 에 해당하는 문자열을 찾고 싶지만 위의 예제를 살펴보면, s에마 1회 이상을 뜻하는 + 기호가 적용되어 js를 반환하는 것이 아닌 jsssss를 반환하는 것을 볼 수 있다.

 

이럴 때에는 그룹화 기호를 사용하여 j와 s를 그룹화해주면 된다.

let str = 'jsssss jsssss';

let rst = str.match(/(js)+/);
console.log(rst);  // [ 'js', 'js', index: 0, input: 'jsssss jsssss', groups: undefined ]

 

하지만 다음의 예제를 보면,

let str = 'jsjsjs';

let rst = str.match(/(js)+/);
console.log(rst);  // [ 'jsjsjs', 'js', index: 0, input: 'jsjsjs', groups: undefined ]

 

jsjsjs 하나만 검색하려고 했는데 플래그 g를 사용하지 않았음에도 js 라는 원하지 않는 결과를 얻었다. 이러한 결과가 발생한 이유는 바로 정규식의 캡쳐 기능 때문이다.

 

패턴 그룹화는 괄호안에 있는 표현식을 캡쳐한 것을 이용하여 한번 더 추가로 검사한다. 여기서 캡쳐를 한다는 것은 괄호안의 문자열을 기억해두는 것을 말한다. 이를 이용하여 기존의 정규식으로 한번, 기억해둔 괄호안의 문자열로 한번, 총 두번을 검색을 하는 것이다!!

  • (js)+ : 검색 결과 jsjsjs 반환
  • 캡쳐한 js로 검색 : js를 반환

 

그렇기 때문에, 캡쳐 기능을 사용하지 않겠다는 기호 ?: 를 사용하여야 한다. 해당 기호를 사용하면 캡쳐 기능을 수행하지 않기 때문에 아래에제 검색은 1번만 이루어지고 원하는 결과를 얻을 수 있다.

let str = 'jsjsjs';

let rst = str.match(/(?:js)+/);
console.log(rst);  // [ 'jsjsjs', 'js', index: 0, input: 'jsjsjs', groups: undefined ]

 

728x90