可以用正则表达式解决吗?
我有一个值数组:
var arr = ['eiusmod', 'sort', 'incididunt', 'dolor'];
我有一个名为my_html
的字符串,该字符串提供了.html()
<div data-sort="1">
<h1 data-position="1">Lorem ipsum dolor sit amet</h1>
<strong>search here : consectetur adipiscing elit, </strong>
<div>
sed do <u>eiusmod</u> tempor <mark>incididunt</mark> ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure <i>dolor</i> in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
目标:
在变量my_html中为找到的每个单词(在我的arr中)添加一个html标记
<div data-sort="1">
<h1 data-position="1">Lorem ipsum <mark>dolor</mark> sit amet</h1>
<strong>search here : consectetur adipiscing elit, </strong>
<div>
sed do <u><mark>eiusmod</mark></u> tempor <mark>incididunt</mark> ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure <i><mark>dolor</mark></i> in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
规则:
感谢您的帮助, 问候
答案 0 :(得分:3)
规则:请勿在标签的属性中添加标签
您不能仅使用简单的正则表达式来执行此操作;您需要一个HTML解析器。如果您在浏览器环境中执行此操作,则有一个内置的。但是几乎无论您在什么环境中进行此操作,都可以使用HTML解析器(Node.js,Java,PHP等)。
This answer显示了如何在浏览器中执行此操作。为了完整起见,以下代码适合您的示例(请参见注释):
// The array
var arr = ['eiusmod', 'sort', 'incididunt', 'dolor'];
// Create a regular expression that's an alternation of the words.
// This assumes no characters in the words that are special in regular
// expressions; if that assumption isn't valid, run the array through
// a regex-escaper function first.
var rex = new RegExp("\\b(?:" + arr.join("|") + ")\\b", "g");
// The string
var str =
"<div data-sort=\"1\">" +
"<h1 data-position=\"1\">Lorem ipsum dolor sit amet</h1>" +
"<strong>search here : consectetur adipiscing elit, </strong>" +
"<div>" +
"sed do <u>eiusmod</u> tempor incididunt dolor ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." +
"</div>" +
"Duis aute irure <i>dolor</i> in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." +
"</div>";
// Parse it into a temporary div
var div = document.createElement("div");
div.innerHTML = str;
// Do the updates
doReplacements(div);
console.log("done");
// Get and show the result
str = div.innerHTML;
console.log(str);
function doReplacements(element) {
// Loop through the children of this element
var child = element.firstChild
while (child) {
switch (child.nodeType) {
case 3: // Text node
// Update its text
child = handleText(child);
break;
case 1: // Element
// Recurse to handle this element's children
doReplacements(child);
child = child.nextSibling;
break;
default:
child = child.nextSibling;
break;
}
}
}
function handleText(node) {
var match, targetNode, followingNode, wrapper;
// Find the first of our target words in this node's text
rex.lastIndex = 0;
match = rex.exec(node.nodeValue);
if (match) {
// Split at the beginning of the match
targetNode = node.splitText(match.index);
// Split at the end of the match
followingNode = targetNode.splitText(match[0].length);
// Wrap the target in a "mark" element
wrapper = document.createElement('mark');
targetNode.parentNode.insertBefore(wrapper, targetNode);
// Now we move the target text inside it
wrapper.appendChild(targetNode);
// Clean up any empty nodes (in case the target text
// was at the beginning or end of a text node)
if (node.nodeValue.length == 0) {
node.parentNode.removeChild(node);
}
if (followingNode.nodeValue.length == 0) {
followingNode.parentNode.removeChild(followingNode);
}
}
// Return the next node to process, which is the sibling after our
// wrapper if we added one, or after `node` if we didn't
return (wrapper || node).nextSibling;
}
答案 1 :(得分:0)
修改
更改了答案以处理评论中的案例。但是T.J.并应该使用它。只需修改他的正则表达式即可处理变音符号(一种方法可以在我的RE中看到)。
此外,此新解决方案使用IE无法处理的 sticky 标志。
另一个正则表达式答案(请不要讨厌我;)
RE:
/<mark>[^<>]+<\/mark>|<[^>]*(?=>)|(^|[^a-zA-Z\u00C0-\u017F])(eiusmod|sort|incididunt|dolor|única)(?=[^a-zA-Z\u00C0-\u017F]|$)|[\s\S]/yi
现在它更加依赖代码,但应该可以工作。它使用交替来标识输入的部分。多亏了 sticky 标志y
,它被强制匹配输入字符串的每个部分。在重要性降序中:
<mark>
。<div class="pa-title" data-title-en="" style="margin-left:0px;">
重复此操作,直到没有匹配为止。结果字符串是根据匹配结果生成的。如果存在捕获组2,表示捕获组2是列表中的匹配单词,则在该单词周围添加mark
标签。
但是,正如一些人指出的那样-例如,如果您尝试抓取任意网页,则必将失败-使用HTML解析器。考虑满足上述条件的属性中使用的单词...
如果您使用的是一组有限的已知页面,则使用正则表达式将是可行的。
生活看起来像这样:
const regex = /<mark>[^<>]+<\/mark>|<[^>]*(?=>)|(^|[^a-zA-Z\u00C0-\u017F])(eiusmod|sort|incididunt|dolor|única)(?=[^a-zA-Z\u00C0-\u017F]|$)|[\s\S]/yi;
const str = `dolor <div data-sort="1">
<h1 data-position="1" eiusmod="foo" >Lorem ipsum dolor sit amet</h1>
<div data="eiusmod"></div>
<strong>search here : consectetur adipiscing elit, </strong>
<div>
sed do <u>eiusmod</u> tempor <mark>incididunt</mark> ut única et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure <i>dolor</i> dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div><div id="pa_3577" class="pa-title" data-title-en="" style="margin-left:0px;">1.</div><div class="pa-content" style="margin-left:62px;"><p>Con la única salvedad que expresaré adelante, comparto plenamente el contenido de esta Decisión unánime.</p></div>
document.js:613:8<br/>
dolor et <mark>dolor</mark> et dolor<br/>
<a>úúnica</a> púnica dolor et dolor et dolor<br/>`;
const subst = "$1$2<mark>$3</mark>";
var result = '',
array1;
while ((array1 = regex.exec(str)) !== null) {
// console.log( '#' + array1[0] + '#' + array1[1] + '#' + array1[2] + '#' );
if(array1[2] != undefined)
result += array1[1] + '<mark>' + array1[2] + '</mark>';
else
result += array1[0];
}
//console.log( result );
document.write( result );
答案 2 :(得分:-1)
正确的做法是使用一些HTML解析器。但是,我会用正则表达式来吸引您:-)
搜索:((?:<[^>]*>[^<]*?)*?(?:(?!<mark>)<[^>]*(?=>))?)(\W|^)(eiusmod|sort|incididunt|dolor|única|feté)(?=\W|$)
替换为:$1$2<mark>$3</mark>
const regex = /((?:<[^>]*>[^<]*?)*?(?:(?!<mark>)<[^>]*(?=>))?)(\W|^)(eiusmod|sort|incididunt|dolor|única|feté)(?=\W|$)/gmu;
const subst = `$1$2<mark>$3</mark>`;
const str = `
única<div data-sort="1">
<p>dolor</p>
<p>única</p>
<h1 data-position="1" eiusmod="foo" >Lorem ipsum dolor sit amet</h1>
<div data="eiusmod"></div>
<strong>search here : consectetur adipiscing elit, </strong>
<div>
sed do <u>eiusmod</u> tempor <mark>incididunt</mark> ut dolor et dolor dolor magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Duis aute irure <i>dolor</i> dolor in dolor dolor reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div>
sed do <u>eiusmod</u> tempor <mark>incididunt</mark> ut única et única púnica magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
<div>fetén</div>`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
document.write(result);
最大的困难是javascript not working ok with unicode characters and word boundaries(因此,试图找到única
却没有找到punica
的问题)