0

Please consider the following example:

let string = '<h2>Some content here</h2><p>Foo Bar</p><h2>Different content here</h2>'

I want to replace what's in between <h2> and </h2>.

I tried the following approach:

string.replace(/<h2.*<\/h2>/, '<h2>xxyyzz</h2>');

But the above solutions transforms string into:

<h2>xxyyzz</h2>

Expected result:

'<h2>xxyyzz</h2><p>Foo Bar</p><h2>xxyyzz</h2>'

How can I replace what's in-between all occurrences of two substrings?

Dharman
  • 30,962
  • 25
  • 85
  • 135
Vingtoft
  • 13,368
  • 23
  • 86
  • 135
  • 1
    Is there a reason you are not using the DOM API to make these changes? Quantifiers are *greedy* by default, i.e. they match the *longest* substring. – Felix Kling Feb 11 '21 at 14:19
  • @FelixKling Yes, the algorithm will run serverside, and there is a reason why it cannot be done client side. – Vingtoft Feb 11 '21 at 14:21
  • 1
    There are also HTML parsers for Node. Just something to consider, depending on how complex the input really is. – Felix Kling Feb 11 '21 at 14:22

3 Answers3

1

let string = '<h2>Some content here</h2><p>Foo Bar</p><h2>Different content here</h2>'
string = string.replace(/<h2>[\s\S]*?<\/h2>/g, '<h2>ABCDEF<\/h2>');
console.log(string);

Pure javascript alternative

let string = '<h2>Some content here</h2><p>Foo Bar</p><h2>Different content here</h2>'
let tmpele = document.createElement('div');
tmpele.innerHTML = string;

let hs = tmpele.getElementsByTagName('h2');
for(let i = 0;i < hs.length; i++) {
    hs[i].innerHTML = 'ABCDEF'
}
console.log(tmpele.innerHTML);
0stone0
  • 34,288
  • 4
  • 39
  • 64
1

One of the approach will be to adjust your regex:

let string = '<h2>Some content here</h2><p>Foo Bar</p><h2>Different content here</h2>';
string = string.replace(/<h2>(.*?)<\/h2>/gm, '<h2>xxyyzz</h2>');
console.log(string); // <h2>xxyyzz</h2><p>Foo Bar</p><h2>xxyyzz</h2>

Some details/restrictions:

  • tags are case sensitive;
  • g modifier: global. All matches (don't return after first match);
  • m modifier: multi line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string);

Similar question: Regex select all text between tags

Andrew Ymaz
  • 1,863
  • 8
  • 12
0

Your regex takes all including Foo bar part too.

You need to update your regex, eg.

let string = '<h2>Some content here</h2><p>Foo Bar</p><h2>Different content here</h2>';

alert(string.replace(/<h2>[^<]+<\/h2>/g, '<h2>xxyyzz</h2>'));
pavel
  • 26,538
  • 10
  • 45
  • 61