LHJ

I'm a FE developer.

17.15 그룹 교체

30 May 2020 » js_lj

17.15 그룹 교체

그룹을 사용하면 문자열 교체도 더 다양한 방법으로 할 수 있습니다.
이번에도 HTML을 예로 들겠습니다.
<a> 태그에서 href가 아닌 속성을 전부 제거하고 싶다고 합시다.

let html = '<a class="nope" href="/yep">Yep</a>'
html = html.replace(/<a .*?(href=".*?").*?>/, '<a $1>');

역참조와 마찬가지로 모든 그룹은 1로 시작하는 숫자를 할당받습니다.
정규식에서 첫 번째 그룹은 \1이고, 교체할 문자열에서는 $1이 첫 번째 그룹에 해당합니다.
이번에도 소극적 일치를 써서 <a> 태그까지 검색이 확장되는 일을 막았습니다.
이 정규식은 href 속성의 값에 큰 따옴표가 아니라 작은따옴표를 쓴 문자열에서는 아무 것도 찾지 못합니다.

좀 더 복잡한 예제를 봅시다.
class 속성과 href 속성을 남기고 나머지는 모두 없애고 싶습니다.

let html = '<a class="yep" href="/yep" id="nope">Yep</a>';
html = html.replace(/a .*?(class=".*?").*?(href=".*?").*?/, '<a $2 $1>');

이 정규식에서는 class와 href의 순서를 바꾸므로 결과 문자열에서는 href가 앞에 옵니다.
이 정규식은 class 뒤에 href이 있어야만 동작하고, 앞에서와 마찬가지로 속성 값에 작은따옴표를 쓰면 동작하지 않습니다.
다음 섹션에서 더 좋은 방법을 알아볼 겁니다.

더 좋은 방법

$1, $2 등 숫자로 참조하는 것 외에도 일치하는 것 앞에 있는 전부를 참조하는 $`, 일치하는 것 자체인 $&, 일치하는 것 뒤에 있는 전부를 참조하는 $' 도 있습니다.
달러 기호 자체가 필요할 때는 $$를 씁니다.

const 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"

이 기능을 사용하는 사람은 그리 많지 않지만, 필자는 이 기능을 써서 아주 스마트하게 문제를 해결한 경우를 몇 번 봤습니다.
잊지 말고 사용해 보십시오.