ES2015에서는 유니코드(/u
) 및 고정 (/y
) 플래그를 사용한 정규 표현식 문법의 상당한 개선사항을 비롯하여 JavaScript 언어에 많은 새로운 기능을 도입했습니다. 하지만 그 이후로 개발은 계속되었습니다. V8팀은 TC39 (ECMAScript 표준 기관)의 다른 회원들과 긴밀히 협력하여 정규 표현식을 더욱 강력하게 만드는 몇 가지 새로운 기능을 제안하고 공동 설계했습니다.
이러한 기능은 현재 JavaScript 사양에 포함하기 위해 제안되고 있습니다. 제안서가 완전히 수락되지는 않았지만 이미 TC39 프로세스의 3단계에 있습니다. 사양이 완성되기 전에 각 제안서 작성자에게 적시에 설계 및 구현 관련 의견을 제공할 수 있도록 이러한 기능을 플래그 (아래 참고) 뒤에 구현했습니다.
이 블로그 게시물에서는 이러한 흥미로운 미래를 미리 살펴볼 수 있습니다. 다음 예시를 따라하려면 chrome://flags/#enable-javascript-harmony
에서 실험용 JavaScript 기능을 사용 설정하세요.
이름이 지정된 캡처
정규 표현식에는 일치하는 텍스트의 일부를 캡처할 수 있는 소위 캡처 (또는 그룹)가 포함될 수 있습니다. 지금까지 개발자는 패턴 내 캡처 위치에 따라 결정되는 색인을 통해서만 이러한 캡처를 참조할 수 있었습니다.
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'
하지만 정규 표현식은 이미 읽기, 쓰기, 유지 관리하기가 어렵기로 악명이 높으며 숫자 참조는 더 복잡성을 가중시킬 수 있습니다. 예를 들어 더 긴 패턴에서는 특정 캡처의 색인을 결정하기가 쉽지 않을 수 있습니다.
/(?:(.)(.(?<=[^(])(.)))/ // Index of the last capture?
더 나쁜 것은 패턴을 변경하면 기존의 모든 캡처 색인이 이동할 수 있다는 점입니다.
/(a)(b)(c)\3\2\1/ // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/ // All need to be updated.
이름이 지정된 캡처는 개발자가 캡처에 이름을 할당하여 이러한 문제를 완화하는 데 도움이 되는 예정된 기능입니다. 구문은 Perl, Java, .Net, Ruby와 유사합니다.
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'
이름이 지정된 캡처는 이름이 지정된 역참조 및 String.prototype.replace
를 통해 참조할 수도 있습니다.
// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx'); // true
// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>'); // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd); // 'ba'
이 새로운 기능에 관한 자세한 내용은 사양 제안서에서 확인할 수 있습니다.
dotAll 플래그
기본적으로 정규 표현식의 .
원자는 줄 바꿈 문자를 제외한 모든 문자와 일치합니다.
/foo.bar/u.test('foo\nbar'); // false
제안서에서 /s
플래그를 통해 사용 설정되는 dotAll 모드를 도입합니다. dotAll 모드에서 .
는 줄 바꿈 문자와도 일치합니다.
/foo.bar/su.test('foo\nbar'); // true
이 새로운 기능에 관한 자세한 내용은 사양 제안서에서 확인할 수 있습니다.
유니코드 속성 이스케이프
ES2015에서 유니코드 인식이 도입되면서 숫자로 간주될 수 있는 문자(예: 원 안에 숫자 1: ①) 또는 단어 문자로 간주될 수 있는 문자(예: 눈을 나타내는 중국어 문자: 雪)가 갑자기 더 많이 생겼습니다.
둘 다 \d
또는 \w
와 일치시킬 수 없습니다. 이러한 약어의 의미를 변경하면 기존 정규 표현식 패턴이 손상됩니다.
대신 새로운 속성 이스케이프 시퀀스가 도입됩니다.
/u
플래그로 표시된 유니코드 인식 정규 표현식에만 사용할 수 있습니다.
/\p{Number}/u.test('①'); // true
/\p{Alphabetic}/u.test('雪'); // true
역은 \P
로 일치시킬 수 있습니다.
/\P{Number}/u.test('①'); // false
/\P{Alphabetic}/u.test('雪'); // false
유니코드 컨소시엄은 수학 기호나 일본어 가나 문자와 같은 더 많은 속성을 정의합니다.
/^\p{Math}+$/u.test('∛∞∉'); // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな'); // true
지원되는 Unicode 속성 클래스의 전체 목록은 현재 사양 제안서에서 확인할 수 있습니다. 자세한 예는 이 유용한 도움말을 참고하세요.
뒤처리 어설션
선행 어설션은 처음부터 JavaScript의 정규 표현식 문법의 일부였습니다. 이에 상응하는 뒤처리 어설션이 마침내 도입됩니다. 이미 오래 전부터 V8의 일부였음을 기억하는 분들도 있을 것입니다. ES2015에 지정된 유니코드 플래그를 구현하기 위해 내부적으로 뒤처리 어설션을 사용하기도 합니다.
이름이 이미 의미를 잘 설명합니다. 뒤처리 그룹의 패턴이 앞에 오는 경우에만 일치하도록 패턴을 제한하는 방법을 제공합니다. 일치하는 버전과 일치하지 않는 버전이 있습니다.
/(?<=\$)\d+/.exec('$1 is worth about ¥123'); // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123'); // ['123']
자세한 내용은 뒤로 탐색 어설션에 관한 이전 블로그 게시물과 관련 V8 테스트 사례의 예시를 참고하세요.
감사의 말씀
이 블로그 게시물은 이를 실현하기 위해 노력한 몇몇 사람들, 특히 언어 챔피언인 마티아스 바이넨스, 댄 에른버그, 클라우드 파체, 브라이언 털슨, 토마스 우드, 고르켐 야킨, Irregexp 전문가인 에릭 코리뿐만 아니라 언어 사양 및 이러한 기능의 V8 구현에 기여한 모든 사람에게 감사의 인사를 전하지 않고는 완성되지 않을 것입니다.
새로운 정규식 기능이 마음에 드시기를 바랍니다.