JavaScript 정규표현식 기초:이론과 사용 방법 및 예제

최근 JavaScript 코딩 중 특정 문자열의 중간에 들어가는 값을 추출할 일이 발생해 정규식(혹은 정규표현식)을 이용하여 이를 해결 하였다.

정규식은 이처럼 문자열을 찾아 가져오거나 이를 다른 단어 등으로 대체 할 때 사용할 수 있는 강력한 규칙, 패턴을 말한다.

정규표현식

정규식은 문자열을 해석하는 규칙을 정의하여 사용 하는 것이다.

예를 들어 우리가 ABCD 라는 문자가 있을 때, 이 A와 D 사이의 BC란 값을 추출 하고 싶을 때 기존에 배운 반복문과 조건문을 통해 이를 수행 할 수 있다.

function extractBetweenAandD(str) {
    let result = ""; // 추출할 문자열을 저장할 변수
    let foundA = false; // 'a'를 찾았는지 여부

    for (let i = 0; i < str.length; i++) {
        if (str[i] === 'a') {
            foundA = true; // 'a'를 찾으면 foundA를 true로 설정
        } else if (str[i] === 'd' && foundA) {
            // 'd'를 찾고 'a'가 이미 찾아졌다면 반복 종료
            break;
        } else if (foundA) {
            // 'a'를 찾은 후 'd'를 찾기 전까지의 문자들을 result에 추가
            result += str[i];
        }
    }

    return result; // 결과 반환
}

const inputStr = "abcd";
const extractedStr = extractBetweenAandD(inputStr);
console.log(extractedStr); // 출력: "bc"
JavaScript

그런데 이는 유리가 하고 싶은 작업을 프로그래밍 적으로 구상해서 구현했기에 동작을 해석해야 하며 복잡한 추출을 원할 경우(특정 A 가 아닌 문장 사이 등) 수정 시 오류가 발생 할 수 있다.

이에 정규표현식은 방금 말한 작업 자체를 수행할 수 있는 식 자체로 표현할 수 있어 규칙을 알고 있다면 더욱 동작을 명확하게 이해하고 예상할 수 있게 됬다. 또 한, 유지 보수 측면 에서도 코드가 간결해 지며 가독성이 좋아진다.

아래 코드는 위의 코드를 정규식을 이용한 코드로 변환한 코드이다.

function extractBetweenAandDWithRegex(str) {
    const regex = /a(.*?)d/; // 'a'와 'd' 사이의 모든 문자를 비탐욕적(greedy) 방식으로 매칭
    const match = str.match(regex);

    return match ? match[1] : ''; // 매칭된 그룹(괄호 안의 패턴)이 있다면 반환, 없으면 빈 문자열 반환
}

const inputStr = "abcd";
const extractedStrWithRegex = extractBetweenAandDWithRegex(inputStr);
console.log(extractedStrWithRegex); // 출력: "bc"
JavaScript

위의 코드에서 regex 변수(정규표현식은 엉어로 Regular Expression 로 주로 변수 regex 로 축약되어 자주 사용 된다.) 에 담긴 값이 정규식이다.

저 식을 응용하면 a와 b를 다른 단어 교체하면 다른 문자열 사이의 값을 추출 할 수 있다.

정규식 사용 기본 방법

정규식은 기본적으로 두 가지를 통해 선언, 사용 되는데 바로 리터럴 문법을 이용하는 것과 생성자 함수를 이용하는 방법으로 사용된다.

리터럴 문법

리터럴 문법은 객체, 배열, 정규식 등에서 데이터 값을 직접적으로 표현하는 방식을 이야기 한다. 쉽게 예를 들면 변수에 값을 넣을 때, 우리가 이 값이 숫자, 문자인지 표현할 방법을 미리 문법을 정해둔 것이다.

변수에 값을 넣을 때 숫자를 바로 쓰면 이는 숫자고 따옴표를 넣으면 문자열로 인식하는 것이 바로 이 문법이다. 그래서 위처럼 내가 지금 사용하는 값이 정규식이다 표현할 땐 슬래시(/) 로 값을 감싸서 표현한다. (예: /abc/)

리터럴 문법 예시 목록:

  • 숫자 리터럴: 1, 2, 3, 4등의 숫자 값을 바로 입력한다.
  • 문자열 리터럴: “a”, “b”, ‘hello’ 등, 작은 따옴표 혹은 큰 따옴표로 감싸 표현한다. 숫자도 감싸게 되면 문자열로 인식한다.
  • 불리언 리터럴: true, false 로 바로 작성한다.
  • 배열 리터럴: [1, 2, 3], [‘a’, ‘b’, ‘c’] 등 대 괄호로 감싸 표현한다.
  • 객체 리터럴: {key1: ‘value’, key2: ‘value’} 등 중괄호와 키-값 쌍을 사용하여 표현한다.
  • 정규식 리터럴: /abc/ 등 정규식을 슬래시(/)로 둘러싸서 표현한다.

생성자 함수

Java 와 같이 new 키워드를 이용한 생성자 함수가 JavaScript 에서도 존재 하는데 이를 이용하여 정규식을 생성하고 변수에 할당, 각종 메소드에서 이용이 가능하다.

정규식의 생성자는 RegExp 이며 생성자 함수는 new RegExp(“패턴”, “수식자”) 가 된다. 위의 예시 코드의 /a(.*?)d/ 코드는 수식자가 없이 패턴만 존재 하므로 생성자 함수로 치환하면 다음과 같이 코드를 작성할 수 있다.

const regex = new RegExp("a(.*?)d");
JavaScript

match 메소드

match 메소드는 정규식에 맞는 결과를 찾아 배열로 이를 반환해 주는 코드이다. 위의 같은 경우 a와 d 사이의 문자를 가져오란 정규식을 이용 했으니, 내가 탐색한 문자열 abcd 가 0번에 담기고 추출한 결과가 1번에 담긴다.

const str = 'abcd'; 
const regex = /a(.*?)d/; // 'a'와 'd' 사이의 모든 문자를 비탐욕적(greedy) 방식으로 매칭
const match = str.match(regex);

console.log(match);
JavaScript
match 메소드 출력 결과

정규식 주요 패턴 및 수식자

정규식에서 자주 사용 되는 주요한 패턴 및 수식자는 다음과 같다.

  • 수식자:
    • g (글로벌 검색)
    • i (대소문자 구분 안 함)
    • m (여러 줄 검색)
  • 패턴:
    • ^ (문자열의 시작)
    • $ (문자열의 끝)
    • . (임의의 한 문자)
    • * (앞 문자가 0회 이상 반복)
    • + (앞 문자가 1회 이상 반복)
    • ? (앞 문자가 0회 또는 1회 등장)
    • \d (숫자와 매치)
    • \w (문자와 매치)
    • [abc] (괄호 안의 어느 한 문자와 매치)
    • (x|y) (x 또는 y와 매치)

위의 목록을 보며 방금 사용한 a(.*?)d 에서 괄호 안을 해석해보자.

괄호는 그룹을 만드는 것이고 . 는 임의의 문자, * 는 바로 앞의 문자 (이 경우는 임의의 문자) 가 없거나 여러 개 있을 수 있다는 의미다. 마지막 ?는 비탐욕적(non-greedy) 라 표현 되는데, 표현 될 수 있는 가장 짧은 문자를 가져온다는 의미이다.

이 말이 어려울 수 있는데 예를 들어, 주어진 문장 중 abcd 의 경우 a 와 d 사이의 문자가 bc 지만 abcded 면 bcde 또한 a와 d의 문자다. 이런 경우 가장 짧은 형태 (제일 빠르게 서치 된) bc 만 출력 된다는 의미다.

따라서, 이를 정리해 표현하면 a(.*?)d 는 a와 d 사이에 임의의 문자(모든 문자) 를 가장 짧은 형태로 가져오고, 없으면 공백으로 가져오란 소리다.

여기서 * 를 1회 이상 반복을 의미하는 + 로 바꾸면 반드시 하나 이상의 문자가 존재해야 된다는 의미로 .match 메소드 에서 매칭이 실패 한다.

const regex1 = /a(.*?)d/; // 'a'와 'd' 사이의 모든 문자를 비탐욕적(greedy) 방식으로 매칭
const regex2 = /a(.+?)d/; // * 를 + 로 변경

console.log(str.match(regex1)); // 1번 위치에 공백이 포함된 배열 출력
console.log(str.match(regex2)); // null 출력
JavaScript
정규식 패턴 이해를 위한 *, + 바꾸고 출력한 예시 코드
0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x
목차
위로 스크롤