Lucas Luan de Melo
Lucas Luan de Melo

Reputation: 152

regex replace first element

I have the need to replace a HTML string's contents from one <br> to two. But what I can't achieve is when I have one tag following another one:

(<br\s*\/?>)

will match all the tags in this text:

var text = 'text<BR><BR>text text<BR>text;'

will match and with the replace I will have

text = text.replace.replace(/(<br\s*\/?>)>/gi, "<BR\/><BR\/>")

console.log(text); //text<BR/><BR/><BR/><BR/>text text<BR/><BR/>text;"

Is there a way to only increment one tag with the regex? And achieve this:

console.log(text); //text<BR/><BR/><BR/>text text<BR/><BR/>text;"

Or I only will achieve this with a loop?

Upvotes: 1

Views: 449

Answers (2)

akuiper
akuiper

Reputation: 214957

You can use negative look ahead (<br\s*\/?>)(?!<br\s*\/?>)/ to increment only the last tag if there are any consecutive:

var text = 'text<BR><BR>text text<BR>text;'

text = text.replace(/(<br\s*\/?>)(?!<br\s*\/?>)/gi, "<BR\/><BR\/>")

console.log(text);

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626845

You may use either

var text = 'text<BR><BR>text text<BR>text;'
text = text.replace(/(<br\s*\/?>)+/gi, "$&$1");
console.log(text); // => text<BR><BR><BR>text text<BR><BR>text;

Here, (<br\s*\/?>)+/gi matches 1 or more sequences of <br>s in a case insensitive way while capturing each tag on its way (keeping the last value in the group beffer after the last it, and "$&$1" will replace with the whole match ($&) and will add the last <br> with $1.

Or

var text = 'text<BR><BR>text text<BR>text;'
text = text.replace(/(?:<br\s*\/?>)+/gi, function ($0) {
 return $0.replace(/<br\s*\/?>/gi, "<BR/>") + "<BR/>";
})
console.log(text); // => text<BR/><BR/><BR/>text text<BR/><BR/>text;

Here, the (?:<br\s*\/?>)+ will also match 1 or more <br>s but without capturing each occurrence, and inside the callback, all <br>s will get normalized as <BR/> and a <BR/> will get appended to the result.

Upvotes: 2

Related Questions