How to replace text not within a specific-Tag in JavaScript
I have a string (partly HTML) where I want to replace the string :-)
into bbcode :wink:
. But this replacement should not happen within <开发者_高级运维pre>
, but in any other tag (or even not within a tag).
For example, I want to replace
:-)<pre>:-)</pre><blockquote>:-)</blockquote>
to:
:wink:<pre>:-)</pre><blockquote>:wink:</blockquote>
I already tried it with the following RegEx, but it does not work (nothing gets replaced):
var s = ':-)<pre>:-)</pre><blockquote>:-)</blockquote>';
var regex = /:\-\)(?!(^<pre>).*<\/pre>)/g;
var r = s.replace(regex, ':wink:');
Can someone please help me? :-)
This ought to do it:-
var src = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>"
var result = src.replace(/(<pre>(?:[^<](?!\/pre))*<\/pre>)|(\:\-\))/gi, fnCallback)
function fnCallback(s)
{
if (s == ":-)") return ":wink:"
return s;
}
alert(result);
It works because any pre
element will get picked up by the first option in the regex and once consumed means that any contained :-) can't be matched since the processor will have moved beyond it.
You could avoid hellish regexes altogether if you use a suitable library such as jQuery, e.g.:
var excludeThese = ['pre'];
// loop over all elements on page, replacing :-) with :wink: for anything
// that is *not* a tag name in the excludeThese array
$('* not:(' + excludeThese.join(',') + ')').each(function() {
$(this).html($(this).html().replace(/:\-\)/,':wink:'));
});
Just thought it'd be worth offering a DOM solution:
E.g.
var div = document.createElement('div');
div.innerHTML = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>";
replace(div, /:-\)/g, ":wink:", function(){
// Custom filter function.
// Returns false for <pre> elements.
return this.nodeName.toLowerCase() !== 'pre';
});
div.innerHTML; // <== here's your new string!
And here's the replace
function:
function replace(element, regex, replacement, filter) {
var cur = element.firstChild;
if (cur) do {
if ( !filter || filter.call(cur) ) {
if ( cur.nodeType == 1 ) {
replace( cur, regex, replacement );
} else {
cur.data = cur.data.replace( regex, replacement );
}
}
} while ( cur = cur.nextSibling );
}
Almost good: Your negative lookbehind and lookahead where not in the right position and need a slight adjustment:
/(?<!(<pre>)):-\)(?!(<\/pre>))/g
- Looks for all ":-)"
- ...but not if there is a <pre> behind (the regex cursor is!)
- ...but not if there is a </pre> before (the regex cursor is!)
as a side effect though: <pre>:-):-)</pre>
works too but not <pre>:-):-):-)</pre>
https://regex101.com/r/CO0DAD/1
ps. this is a firefox 104 browser (could be different in others)
try with var regex = /:-)(?!(^)*</pre>)/g;
精彩评论