RegExp

RegExp

RegExp 객체는 패턴을 이용해 텍스트를 매칭할 때 사용됩니다. 정규 표현식 문법과 사용법을 제공하며, 리터럴 표기와 생성자 두 가지 방식으로 만들 수 있습니다.

출처: RegExp - JavaScript | MDN

본문

RegExp 객체는 패턴으로 텍스트를 매칭하는 데 사용됩니다. 정규 표현식에 대한 입문은 JavaScript 안내서의 "Regular expressions" 장을, 문법에 대한 자세한 정보는 정규 표현식 참조를 읽으세요.

리터럴 표기와 생성자

RegExp 객체를 만드는 방법은 리터럴 표기(literal notation)와 생성자(constructor) 두 가지가 있습니다.

리터럴 표기는 두 슬래시 사이에 패턴을 넣고, 두 번째 슬래시 뒤에 선택적 플래그를 붙입니다. 생성자 함수는 첫 번째 파라미터로 문자열이나 RegExp 객체를, 두 번째 파라미터로 선택적 플래그 문자열을 받습니다.

다음 세 표현은 모두 동일한 정규 표현식 객체를 만듭니다.

const re = /ab+c/i; // 리터럴 표기
// 또는
const re = new RegExp("ab+c", "i"); // 첫 인자가 문자열 패턴인 생성자
// 또는
const re = new RegExp(/ab+c/, "i"); // 첫 인자가 정규 표현식 리터럴인 생성자

정규 표현식은 사용되기 전에 컴파일되어야 합니다. 이 과정 덕분에 더 효율적으로 매칭을 수행할 수 있습니다. 리터럴 표기는 표현식이 평가될 때 정규 표현식을 컴파일하는 반면, RegExp 생성자(new RegExp('ab+c'))는 런타임에 정규 표현식을 컴파일합니다. 동적 입력으로 정규 표현식을 만들고 싶다면 RegExp() 생성자에 문자열을 첫 인자로 전달하세요.

생성자의 플래그new RegExp(/ab+c/, flags) 표현식은 첫 파라미터의 소스와 두 번째 파라미터의 플래그로 새 RegExp를 만듭니다. 생성자 함수를 사용할 때는 일반적인 문자열 이스케이프 규칙(문자열에 포함할 때 특수 문자 앞에 \를 붙이는 것)이 필요합니다. 예를 들어 다음 두 표현은 동일합니다.

const re = /\w+/;
// 또는
const re = new RegExp("\\w+");

정규 표현식의 특별 취급

어떤 것이 "regex"인지는 덕 타이핑(duck-typing)될 수 있습니다. 실제 RegExp일 필요는 없습니다. 일부 내장 메서드는 x가 Symbol.match 속성(진실 값)을 가지는지 등 여러 단계를 거쳐 정규 표현식인지 판단합니다. 이 선택은 [Symbol.match]()가 매칭에 사용되도록 의도된 속성을 가장 잘 나타내기 때문입니다.

정규 표현식을 특별 취급하는 곳에는 다음이 포함됩니다.

  • String.prototype.endsWith(), startsWith(), includes()는 첫 인자가 정규 표현식이면 TypeError를 던집니다.
  • String.prototype.matchAll()replaceAll()은 첫 인자가 정규 표현식일 때 [Symbol.matchAll]() 또는 [Symbol.replace]() 메서드를 호출하기 전에 global 플래그가 설정되었는지 확인합니다.
  • RegExp() 생성자는 패턴이 정규 표현식일 때(몇 가지 다른 조건 포함) 패턴 인자를 직접 반환합니다.

예를 들어 String.prototype.endsWith()는 모든 입력을 문자열로 강제 변환하지만, 인자가 정규 표현식이면 던집니다. 정규 표현식만 매칭 대상이므로, 정규 표현식을 쓰는 것은 개발자 실수일 가능성이 높기 때문입니다.

"foobar".endsWith({ toString: () => "bar" }); // true
"foobar".endsWith(/bar/); // TypeError: First argument to String.prototype.endsWith must not be a regular expression

[Symbol.match]undefined가 아닌 거짓 값으로 설정하면 이 검사를 우회할 수 있습니다.

Perl 스타일의 RegExp 속성

여러 RegExp 속성은 길고 짧은(Perl 스타일) 이름을 둘 다 갖습니다. 두 이름은 항상 같은 값을 가리킵니다. (Perl은 JavaScript가 정규 표현식을 본떠 만든 프로그래밍 언어입니다.)

생성자

  • RegExp() — 새 RegExp 객체를 만듭니다.

정적 속성

  • RegExp.$1, …, RegExp.$9 — 괄호로 묶인 부분 문자열 매치를 담은 정적 읽기 전용 속성.
  • RegExp.input ($_) — 정규 표현식이 성공적으로 매칭된 마지막 문자열을 담는 정적 속성.
  • RegExp.lastMatch ($&) — 마지막으로 매칭된 부분 문자열을 담는 정적 읽기 전용 속성.
  • RegExp.lastParen ($+) — 마지막 괄호로 묶인 부분 문자열 매치를 담는 정적 읽기 전용 속성.
  • RegExp.leftContext ($)` — 가장 최근 매치 앞의 부분 문자열을 담는 정적 읽기 전용 속성.
  • RegExp.rightContext ($') — 가장 최근 매치 뒤의 부분 문자열을 담는 정적 읽기 전용 속성.
  • RegExp[Symbol.species] — 파생 객체를 만드는 데 사용되는 생성자 함수.

정적 메서드

  • RegExp.escape() — 문자열의 잠재적 정규 표현식 문법 문자를 이스케이프하고, RegExp() 생성자의 리터럴 패턴으로 안전하게 사용할 수 있는 새 문자열을 반환합니다.

인스턴스 속성

RegExp.prototype에 정의되어 모든 RegExp 인스턴스가 공유하는 속성: constructor, dotAll(.이 줄바꿈과 매치되는지), flags, global, hasIndices, ignoreCase, multiline, source(패턴의 텍스트), sticky, unicode, unicodeSets. 각 인스턴스의 고유 속성으로는 lastIndex(다음 매치를 시작할 인덱스)가 있습니다.

인스턴스 메서드

  • RegExp.prototype.compile() — 스크립트 실행 도중 정규 표현식을 (재)컴파일합니다.
  • RegExp.prototype.exec() — 문자열 파라미터에서 매치를 검색합니다.
  • RegExp.prototype.test() — 문자열 파라미터에서 매치를 테스트합니다.
  • RegExp.prototype.toString() — 지정된 객체를 나타내는 문자열을 반환합니다. Object.prototype.toString() 메서드를 재정의합니다.
  • RegExp.prototype[Symbol.match](), [Symbol.matchAll](), [Symbol.replace](), [Symbol.search](), [Symbol.split]() — 매칭/대체/검색/분할에 사용되는 심볼 메서드들.

예제

정규 표현식으로 데이터 형식 변경String.prototype.replace() 메서드를 사용해 first last 형식의 이름을 last, first 형식으로 바꿉니다. 교체 텍스트에서 $1$2는 정규 표현식 패턴의 해당 매칭 괄호 결과를 나타냅니다.

const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newStr = str.replace(re, "$2, $1");
console.log(newStr); // "Cruz, Maria"

여러 줄 처리 — 기본적으로 . 문자는 줄바꿈과 매치하지 않습니다. 줄바꿈과 매치하게 하려면 s 플래그(dotAll 모드)를 사용하세요.

sticky 플래그y 플래그는 RegExp.prototype.lastIndex에서 시작해 매치를 시도하는 sticky 매칭을 수행합니다. sticky 플래그 y는 다음 매치가 lastIndex 위치에서 일어나야 하지만, global 플래그 glastIndex 위치 또는 그 이후에서 매치가 가능합니다.

유니코드 문자와 정규 표현식\w\W는 ASCII 기반 문자(az, AZ, 0~9, _)만 매치합니다. 키릴 문자나 히브리어 같은 다른 언어 문자를 매치하려면 \uHHHH(HHHH는 16진수 유니코드 값)를 사용하거나 \p{scx=Cyrl} 같은 유니코드 속성 이스케이프를 사용할 수 있습니다.

URL에서 서브도메인 추출console.log(/^https?:\/\/(.+?)\./.exec(url)[1]); 같은 패턴으로 추출할 수 있습니다. 다만 URL 파싱에는 정규 표현식 대신 브라우저 내장 URL API를 사용하는 것이 더 좋습니다.

동적 입력에서 정규 표현식 만들기new RegExp(\b(${breakfasts.join("|")})\b, "g")처럼 문자열을 조합해 동적으로 정규 표현식을 빌드할 수 있습니다.

Firefox 관련 참고: Firefox 34부터, 그 실행을 방해하는 수량자를 가진 캡처링 그룹의 매치 텍스트는 빈 문자열 대신 undefined가 됩니다. 웹 호환성 때문에 RegExp.$N은 여전히 undefined 대신 빈 문자열을 반환합니다.

더 알아보기

  • 정규 표현식 안내서
  • String.prototype.match(), String.prototype.replace(), String.prototype.split()
  • core-js의 정규 표현식 폴리필