JS RegExp正在查找不在标记和替换字符串中的单词



我需要编写第二个RegExp来查找不在标记中的sentence内的变量d。所以标签中的变量应该被跳过。

Regex'(?:^|\b)('+d+')(?=\b|$)'将找到d变量,但我需要排除具有class="description"<span>标记。新句子用一个新标签包装。

sentence = "This is some word. <span class='description'>word</span> in tag should be skipped"
d = 'word'
re = new RegExp('(?:^|\b)('+d+')(?=\b|$)', 'gi')
sentence = sentence.replace(re, "<span>$1</span>")

我试图实现的结果是:

"This is some <span>word</span>. <span class='description'>word</span> in tag should be skipped"

我在用咖啡脚本,谢谢你的帮助。

试试这个:(word)(?![^<>]*</)

完整代码:

var sentence = "This is some word. <span class='description'>word</span> in tag should be skipped"
var d = 'word'
var re = new RegExp('('+d+')(?![^<>]*</)', 'gi')
sentence = sentence.replace(re, "<span>$1</span>")

我的回答基于以下片段:https://regex101.com/library/gN4vI6

尝试用正则表达式操作HTML不是一个好主意:迟早会遇到一些边界条件,它会失败。也许某些<>出现在属性值内,甚至出现在文本节点内,而搜索到的术语也可能出现在意外的位置,如HTML注释、属性值或脚本标记中。。。边界案例清单很长。

此外,您的搜索词可能包含在正则表达式语法中具有特殊含义的字符,因此您至少应该转义这些字符。

这里有一个解决方案,它使用DOM功能将字符串解释为HTML,并且只替换文本节点中的文本:

function escapeRegExp(str) {
return str.replace(/[[]/{}()*+?.\^$|-]/g, "\$&");
}
function wrapText(sentence, word) {        
const re = new RegExp("\b(" + escapeRegExp(word) + ")\b", "gi"),
span = document.createElement('span');
span.innerHTML = sentence;
Array.from(span.childNodes, function (node) {
if (node.nodeType !== 3) return;
node.nodeValue.split(re).forEach(function (part, i) {
let add;
if (i%2) {
add = document.createElement('span');
add.textContent = part;
add.className = 'someClass';
} else {
add = document.createTextNode(part);
}
span.insertBefore(add, node);
});
span.removeChild(node);
});
return span.innerHTML;
}
const html = 'This is some word. <span class="word">word</span> should stay',
result = wrapText(html, 'word');
console.log(result);

递归到元素

在您提到的注释中,您现在还希望在一些标记中进行替换,如p

我假设您希望所有元素都发生这种情况,除了那些具有特定类的元素,例如您用于包装span元素的类,但您当然可以根据需要自定义条件(例如仅递归到p,或…)

代码只需要一些修改:

function escapeRegExp(str) {
return str.replace(/[[]/{}()*+?.\^$|-]/g, "\$&");
}
function wrapText(sentence, word) {        
const re = new RegExp("\b(" + escapeRegExp(word) + ")\b", "gi"),
doc = document.createElement('span');
doc.innerHTML = sentence;

(function recurse(elem) {
Array.from(elem.childNodes, function (node) {
// Customise this condition as needed:
if (node.classList && !node.classList.contains('someClass')) recurse(node);
if (node.nodeType !== 3) return;
node.nodeValue.split(re).forEach(function (part, i) {
let add;
if (i%2) {
add = document.createElement('span');
add.textContent = part;
add.className = 'someClass';
} else {
add = document.createTextNode(part);
}
elem.insertBefore(add, node);
});
elem.removeChild(node);
});
})(doc);        
return doc.innerHTML;
}
const html = '<p><b>Some word</b></p>. <span class="someClass">word</span> should stay',
result = wrapText(html, 'word');
console.log(result);

最新更新