그룹 교체
그룹을 사용하면 문자열 교체도 더 다양한 방법으로 할 수 있습니다. 이번에도 HTML을 예로 들겠습니다. <a> 태그에서 href가 아닌 속성을 전부 제거하고 싶다고 합시다.
let html = '<a class="nope" href="/yep">Yep</a>';
html = html.replace(/<a .*?(href=".*?").*?>/, '<a $1>');
// <a href="/yep">Yep</a>
역 참조와 마찬가지로 모든 그룹은 1로 시작하는 숫자를 할당받습니다. 정규식에서 첫 번재 그룹은 \1이고, 교체할 문자열에서는 $1이 첫 번째 그룹에 해당합니다. 이번에도 소극적 일치를 써서 다름 <a> 태그까지 검색이 확장되는 일을 막았습니다. 이 정규식은 href 속성의 값에 큰 따옴표가 아니라 작은 따옴표를 쓴 문자열에서는 아무것도 찾지 못합니다.
// munifico's thinking
// 이렇게 하면 됩니다.
html = html.replace(/<a .*?(href=['"].*?['"]).*?>/, '<a $1>');
// <a href="/yep">Yep</a>
// <a href='/yep'>Yep</a>
좀 더 복잡한 예제를 봅시다. class 속성과 href 속성을 남기고 나머지는 모두 없애고 싶습니다.
let html = `<a class='yep' href="/yep" id="nope">Yep</a>`;
html = html.replace(/<a .*?(class=['"].*?['"]).*?(href=['"].*?['"]).*?>/, '<a $2 $1>');
// munifico's thinking
// 작은 따옴표과 큰 따옴표에 상관없이 모두 찾을 수 있도록 수정해보았습니다.
// 책에 있는 원래의 정규식은 다음과 같습니다.
// /<a .*?(class=".*?").*?(href=".*?").*?>/
// <a href="/yep" class='yep'>Yep</a>
이 정규식에서는 class와 href의 순서를 바꾸므로 결과 문자열에서는 href가 앞에 옵니다. 이 정규식은 class 뒤에 href이 있어야만 동작합니다. 다음 섹션에서 더 좋은 방법을 알아볼 겁니다.
$1, $2 등 숫자로 참조하는 것 외에도 일치하는 것 앞에 있는 전부를 참조하는 $`, 일치하는 것 자체인 $&, 일치하는 것 뒤에 있는 전부를 참조하는 $’도 있습니다. 달러 기호 자체가 필요할 때는 $$를 씁니다.
let input = "One two three";
input.replace(/two/, '($`)'); // One (One ) three
input.replace(/two/, '($&)'); // One (two) three
input.replace(/two/, "($')"); // One ( three) three
input.replace(/two/, '($$)'); // One ($) three
이 기능을 사용하는 사람은 그리 많지 않지만, 필자는 이 기능을 써서 아주 스마트하게 문제를 해결한 경우를 몇 번 봤습니다. 잊지 말고 사용해 보십시오.