HyunJun 기술 블로그

정규 표현식, Regular Expression 본문

JavaScript

정규 표현식, Regular Expression

공부 좋아 2023. 7. 21. 09:17
728x90
반응형

정규 표현식(Regular Expression)

정규 표현식은 문자열을 처리하고 검색, 추출, 치환 등의 작업을 수행하는 데 사용되는 강력한 도구이다. 간단한 문자열 매칭에서부터 복잡한 패턴 검색까지 다양한 용도로 활용된다.

 

 

1. 정규 표현식의 기본 구성 요소.

일반적으로 패턴이 없는 특정 문자열을 매칭 시키고 싶을 경우 문자 그대로 표현하면 된다. 예를 들어 "hello"는 그 자체로 문자열 "hello"를 매칭한다.

 

JavaScript에서 정규 표현식 선언은 2가지 방식으로 사용할 수 있다.

const reg1 = /hello/;
const reg2 = new RegExp("hello");

console.log(reg1);
console.log(reg2);

1) match

문자열에 match() 메서드를 사용해서 정규 표현식을 매개 변수로 넘겨주면, 해당 정규 표현식에 매칭되는 정보들을 가지고 온다. 매칭이 되지 않는다면 null을 반환한다. 이때 예를 들어, "hellow".match 하는 경우 "hello"와 매칭되는 부분이 있기 때문에 매칭이 성립된다.

console.log("hello world".match(reg1));
console.log("hi world".match(reg1));

 

 

match() 메서드의 리턴 값을 토대로, 정규 표현식에 매칭되는 값에 대한 배열을 가지고 올 수 있고, replace()에서 정규 표현식을 활용할 수 있다.

console.log("hello world".match(reg1)[0]);
console.log("hello world".replace(reg1, "Hi"));

문자 집합(character class)

이름 그대로 문자 집합에 대해서 매칭이 되는지 확인한다. 위의 예제에서는 "hello"라는 문자열을 정규 표현식으로 설정했을 때 "h"의 앞 문자와 "o"의 뒷 문자는 신경 쓰지 않고 hello가 먼저 매칭되는지 확인을 했다. 그렇다면 만약 "hello" 중 1개의 스펠링만 포함돼도 매칭을 시키려면 어떻게 해야 할까? 문자 집합 "[]"을 이용하여 값을 [hello]로 주면 "h", "e", "l", "l", "o" 가 포함된 한 개의 정규 표현식에 대한 값을 찾는다. 즉 문자열로 매칭하는 게 아닌 하나하나의 문자(char)로 매칭하게 된다.

const reg = /[hello]/;

console.log("h".match(reg));
console.log("e".match(reg));
console.log("l".match(reg));
console.log("l".match(reg));
console.log("o".match(reg));
console.log("hello".match(reg));
console.log("xyz".match(reg));

hello의 경우 가장 먼저 매칭된 1개의 값만 리턴한다.

 

기본적으로 위와 같은 원리이고, 아래의 여러 가지 문자 집합을 사용한다.

  1. 단일 문자 집합 (Single Character Class): 
    • [abc]: "a", "b", "c" 중 하나와 일치한다.
    • [0-9]: 0부터 9까지의 숫자 중 하나와 일치한다.
    • [A-Za-z]: 모든 영문 알파벳 중 하나와 일치한다.
  2. 부정 문자 집합 (Negation Character Class):
    • [^abc]: "a", "b", "c" 이외의 문자 중 하나와 일치한다.
    • [^0-9]: 숫자 이외의 문자 중 하나와 일치한다.
  3. 문자 범위 (Character Range):
    • [a-z]: 소문자 알파벳 중 하나와 일치한다.
    • [A-Z]: 대문자 알파벳 중 하나와 일치한다.
    • [a-zA-Z]: 모든 알파벳 중 하나와 일치한다.
    • [0-9]: 0부터 9까지의 숫자 중 하나와 일치한다.
  4. 여러 문자 집합 연결 (Multiple Character Classes):
    • (apple|banana|grape): "apple", "banana", "grape" 중 하나와 일치한다.
    • ([0-9]|[A-F]): 0부터 9 또는 A부터 F 중 하나와 일치한다.
  5. 특수 문자 집합 (Special Character Class):
    • \d: 숫자와 일치한다. [0-9]와 동일하다.
    • \D: 숫자 이외의 문자와 일치한다. [^0-9]와 동일하다.
    • \w: 단어 문자와 일치한다. [A-Za-z0-9_]와 동일하다.
    • \W: 단어 문자 이외의 문자와 일치한다. [^A-Za-z0-9_]와 동일하다.
    • \s: 공백 문자와 일치한다. (공백, 탭, 줄 바꿈 등)
    • \S: 공백 문자 이외의 문자와 일치한다.

2) flag

만약 위의 예제에서 "hello"에 대해서 하나하나의 문자(char)에 대해서 모두 매칭되는지 확인하려면 어떻게 해야 할까? 이는 기본적으로 정규 표현식 매칭 시 설정이 없다면 타겟 문자열의 왼쪽에서부터 읽어가면서 매칭된 하나의 결과만 리턴하기 때문이다. 이때는 flag라는 것을 사용하면 된다.

 

flag라는 것을 사용하면 정규 표현식 패턴에 옵션들을 적용할 수 있다.

  • i(ignore case): 대소문자를 구분하지 않고 매칭을 수행한다.
  • g(global): 전역 매칭을 수행한다. 기본적으로 match() 메서드는 첫 번째 매칭만 반환하지만, 'g' 플래그를 사용하면 모든 매칭 결과를 반환한다.
  • m(multiline): 여러 줄을 가진 문자열에서도 매칭을 수행한다.

 

const reg = /[hello]/g;

console.log("h".match(reg));
console.log("e".match(reg));
console.log("l".match(reg));
console.log("l".match(reg));
console.log("o".match(reg));
console.log("hello".match(reg));
console.log("xyz".match(reg));

3) exec

match()는 모든 매칭 결과를 배열로 한 번에 반환하는 반면, exec()는 매칭 결과를 순차적으로 하나씩 반환하며, 반복문과 함께 사용하며 모든 매칭 결과를 하나씩 처리할 수 있다. exec()를 사용하면 매칭 결과에 대해 더 세밀한 조작이 가능하므로, 특정 매칭 결과에 대해 자세한 정보를 가져올 수 있다.

const text = "Hello World hello world";
const reg = /hello/gi;

let result;
while ((result = reg.exec(text)) !== null) {
	console.log(result);
}

4) test

test() 메서드는 문자열에서 정규 표현식과 매칭되는지를 확인하는 데 사용한다. 즉, Boolean 값을 리턴한다. 매칭이 되면 true, 안되면 false가 리턴된다. test() 메서드는 'g' 플래그와 상관없이 첫 번째 매칭만 확인한다. 즉, 아래의 코드에서 앞쪽의 "Hello"가 매칭되었을 때 바로 true를 리턴한다.

const text = "Hello World hello world";
const reg = /hello/gi;

console.log(reg.test(text)); // true

5) 메타 문자

특별한 의미를 가지는 문자들이다.

. : 모든 문자와 매칭 (줄바꿈 문자 제외).

* : 앞의 문자가 0번 이상 반복되는 패턴과 매칭.

+ : 앞의 문자가 1번 이상 반복되는 패턴과 매칭.

? : 앞의 문자가 0번 또는 1번 나타나는 패턴과 매칭.

^ : 문자열의 시작과 매칭.

$ : 문자열의 끝과 매칭.

[] : 문자 집합을 나타내며, 해당 위치에 나타날 수 있는 문자를 지정한다.

() : 그룹을 지정하고 매칭 결과를 묶을 수 있다.

 

지금까지의 예제에서는 만약 "apple"을 매칭하려면, "xappley"도 매칭되거나 아니면 "a", "p", "p", ... 등이 매칭되는 방법을 알아보았다. 그렇다면 여러 개의 문자열을 정확히 매칭하려면 어떻게 해야 할까, 예를 들면 "apple", "banana", "orange"에 정확히 매칭되는 정규 표현식을 만들고 싶다면?

const reg = /^apple$|^banana$|^orange$/;

console.log("apple".match(reg)); // "apple"와 일치
console.log("banana".match(reg)); // "banana"와 일치
console.log("orange".match(reg)); // "orange"와 일치
console.log("xapple".match(reg)); // null (앞에 "x"가 있기 때문에 일치하지 않음)
console.log("banana ".match(reg)); // null (뒤에 공백이 있기 때문에 일치하지 않음)

6) grouping

정규 표현식 그룹핑(Grouping)은 괄호 ()를 사용하여 정규식 패턴의 일부를 묶는 것을 말한다. 그룹핑을 사용하면 특정 패턴의 하위 부분을 추출하거나 논리적인 단위로 묶어서 패턴을 구성할 수 있다. 그룹핑은 다음과 같은 목적으로 사용될 수 있다.

 

  1. 하위 패턴 추출: 괄호로 묶인 부분은 매칭 결과의 배열에서 별도의 항목으로 추출할 수 있다.
  2. 반복 패턴: 괄호 안에 반복 횟수를 지정하여 해당 부분이 반복되는 패턴을 나타낼 수 있다.
  3. 논리적 OR 연산: | 기호를 사용하여 여러 패턴 중 하나와 일치하는지 확인할 수 있다.

 

하위 패턴 추출

  const text = "Name: John, Age: 30, Email: john@example.com";

  // 이름과 이메일 주소를 추출하는 그룹핑
  const regex = /Name: (\w+), .* Email: (\w+@\w+\.\w+)/;

  const result = text.match(regex);
  if (result) {
    const name = result[1];
    const email = result[2];
    console.log("Name:", name); // Name: John
    console.log("Email:", email); // Email: john@example.com
  }

 

반복 패턴

const text = "abacbabbbbcabbbccc";

// 'b'가 반복되는 패턴을 그룹핑
const regex = /(b+)/g;

const result = text.match(regex);
console.log(result); // ["b", "bbb", "bb", "b"]

논리 연산

논리 연산을 사용하여 해당 패턴에 매칭되는 값들을 그룹핑 할 수 있다.

const text = "apple, banana, orange, grape";

// "apple", "banana", "orange", "grape" 중 하나와 매칭되는 패턴을 그룹핑
const regex = /(apple|banana|orange|grape)/g;

const result = text.match(regex);
console.log(result); // ["apple", "banana", "orange", "grape"]

2. 코드 예제

전화번호 정규 표현식

  const phoneNumberReg = /^(01[0-9]{1})\-([0-9]{3,4})\-([0-9]{4}$)/;
  const phoneNumberReg2 = /^(01d{1})\-(d{3,4})\-(d{4}$)/;

  let phoneNumber = "010-1234-5678";
  console.log(phoneNumberReg.test(phoneNumber));
  console.log(phoneNumber.match(phoneNumberReg));

 

이메일 정규 표현식

const emailReg = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
let email = "abcd@naver.com";

console.log(email.match(emailReg));
728x90
반응형
Comments