Regular Expression

양세희·2022년 6월 8일
0
post-thumbnail

정규 표현식

정규 표현식, 또는 정규식은 문자열에서 특정 문자 조합을 찾기 위한 패턴이다. JavaScript에서는 정규 표현식도 객체로서, RegExp의 exec()와 test() 메서드를 사용할 수 있다. String의 match(), matchAll(), replace(), replaceAll(), search(), split() 메서드와도 함께 사용할 수 있다.

정규 표현식 만들기

정규 표현식은 두 가지 방법으로 만들 수 있다.

  • 정규 표현식 리터럴
    다음과 같이 슬래시로 패턴을 감싸서 작성한다.
    정규 표현식 리터럴은 스크립트를 불러올 때 컴파일 되므로, 바뀔 일이 없는 패턴의 경우 리터럴을 사용하면 성능이 향상될 수 있다.
const re = /ab+c/
  • RegExp 객체의 생성자 호출
    생성자 함수를 사용하면 정규 표현식이 런타임에 컴파일 된다.
    바뀔 수 있는 패턴이나, 사용자 입력 등 외부 출처에서 가져오는 패턴의 경우 이렇게 사용하면 좋다.
const re = new RegExp('ab+c')

정규 표현식 패턴 작성하기

정규 표현식 패턴은 /ab+c/처럼 단순한 문자로 구성하거나, /ab+c//Chapter (\d+)\.\d*/처럼 단순한 문자와 특수 문자의 조합으로 구성할 수도 있다. 특히 (\d+)에 나타난 괄호는 정규 표현식에서 기억 장치처럼 쓰여서, 괄호의 안쪽 패턴과 일치한 부분을 나중에 사용할 수 있도록 기억한다.

단순 패턴 사용하기

단순 패턴은 문자열을 있는 그대로 탐색할 때 사용한다.
예를 들어, /abc/ 패턴은 문자열에서 정확한 순서로 "abc"라는 문자의 조합이 나타나는 부분과 일치한다. 그러므로 이 패턴은 "Hi, do you know your abc's?""The latest airplane designs evolved from slabcraft." 두 문자열에서 일치에 성공하고, 일치하는 부분은 "abc"일 것이다. 반면 "Grab crab"에서는 일치하지 않는데, 이 문자열은 부분 문자열로 "ab c"를 포함하긴 하지만, 정확하게 "abc"를 포함하지는 않기 때문이다.

특수 문자 사용하기

하나 이상의 "b"를 찾는다거나 공백 문자를 찾는 등 직접적인 일치 이상의 탐색이 필요할 땐 특수 문자를 사용한다. 예를 들어, "하나의 "a" 이후에 0개 이상의 "b", 그 뒤의 "c"와 일치해야 하면 /ab*c/ 패턴을 사용할 수 있다. "b" 뒤의 *"이전 항목의 0번 이상 반복"을 의미한다. 이 패턴을 문자열 "cbbabbbbcdebc"에 대해 사용하면, 일치하는 부분 문자열은 "abbbbc"일 것이다.

이스케이핑

특수 문자를 있는 그대로 탐색("*"을 직접 찾는 등)해야 하는 경우, 특수 문자 앞에 역슬래시()를 배치해서 이스케이프 해야 한다. 예를 들어 "a" 뒤의 별표("*") 뒤의 "b"와 일치해야 하면 /a\*b/를 사용하면 된다. 역슬래시가 "*""이스케이프"해서, 특수 문자가 아닌 문자 리터럴로 취급한다.

마찬가지로, 슬래시(/)와 일치해야 하는 경우에도 이스케이프를 해야 한다. 그냥 빗금을 사용하면 패턴이 끝나버린다. 예를 들어 문자열 "/example/"과 그 뒤 하나 이상의 알파벳을 찾으려면 /\/example\/[a-z]/를 사용할 수 있다. 각각의 슬래시 앞에 놓인 역슬래시가 슬래시를 이스케이프한다.

리터럴 역슬래시에 일치하려면 역슬래시를 이스케이프한다. "A:\", "B:\", "C:\", ..., "Z:\"와 일치하는 패턴은 /[A-Z]:\\/이다. 앞의 역슬래시가 뒤의 역슬래시를 이스케이프해서, 결과적으로 하나의 리터럴 역슬래시와 일치하게 된다.

RegExp 생성자와 문자열 리터럴을 사용하는 경우, 역슬래시가 문자열 리터럴의 이스케이프로도 작동한다는 것을 기억해야 한다. 그러므로 정규 표현식의 역슬래시를 나타내려면 문자열 리터럴 수준의 이스케이프도 해줘야 한다. 즉, 앞서 살펴본 /a\*b/ 패턴을 생성하려면 new RegExp("a\\*b")가 되어야 한다.

이스케이프 되지 않은 문자열을 이미 가지고 있을 땐 String.replace를 활용해 이스케이프를 해줄 수 있다.

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') 
  // $&은 일치한 문자열 전체를 의미
}

정규 표현식 뒤의 "g"는 전체 문자열을 탐색해서 모든 일치를 반환하도록 지정하는 전역 탐색 플래그이다.

괄호 사용하기

정규 표현식의 아무 부분이나 괄호로 감싸게 되면, 그 부분과 일치하는 부분 문자열을 기억하게 된다. 기억한 부분 문자열은 불러와서 다시 사용할 수 있다.

0개의 댓글