在JavaScript字符串中给出关键字时,我需要强调不区分大小写。
例如:
highlight("foobar Foo bar FOO", "foo")
应该返回"<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"
我需要代码适用于任何关键字,因此使用像/foo/i
这样的硬编码正则表达式并不是一个充分的解决方案。
最简单的方法是什么?
(这是标题中详述的更一般问题的一个实例,但我觉得最好用一个具体,有用的例子来解决。)
答案 0 :(得分:69)
如果准备搜索字符串,可以使用正则表达式。在PHP中,例如有一个函数preg_quote,用它们的转义版本替换字符串中的所有正则表达式。
这是javascript的这个功能:
function preg_quote( str ) {
// http://kevin.vanzonneveld.net
// + original by: booeyOH
// + improved by: Ates Goral (http://magnetiq.com)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// * example 1: preg_quote("$40");
// * returns 1: '\$40'
// * example 2: preg_quote("*RRRING* Hello?");
// * returns 2: '\*RRRING\* Hello\?'
// * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
// * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
}
(取自http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_preg_quote/)
所以你可以做以下事情:
function highlight( data, search )
{
return data.replace( new RegExp( "(" + preg_quote( search ) + ")" , 'gi' ), "<b>$1</b>" );
}
答案 1 :(得分:64)
function highlightWords( line, word )
{
var regex = new RegExp( '(' + word + ')', 'gi' );
return line.replace( regex, "<b>$1</b>" );
}
答案 2 :(得分:13)
您可以使用为您执行特殊字符转义的函数来增强RegExp对象:
RegExp.escape = function(str)
{
var specials = /[.*+?|()\[\]{}\\$^]/g; // .*+?|()[]{}\$^
return str.replace(specials, "\\$&");
}
然后你可以毫无后顾之忧地使用别人的建议:
function highlightWordsNoCase(line, word)
{
var regex = new RegExp("(" + RegExp.escape(word) + ")", "gi");
return line.replace(regex, "<b>$1</b>");
}
答案 3 :(得分:5)
正则表达式很好,只要关键字真的是单词,你可以使用RegExp构造函数而不是文字来从变量创建一个:
var re= new RegExp('('+word+')', 'gi');
return s.replace(re, '<b>$1</b>');
如果“关键字”可以包含标点符号,则会出现困难,因为标点符号往往在正则表达式中具有特殊含义。不幸的是,与其他大多数支持regexp的语言/库不同,没有标准函数来逃避JavaScript中的regexp的标点符号。
并且你不能完全确定哪些字符需要转义,因为不是每个浏览器的regexp实现都保证完全相同。 (特别是,较新的浏览器可能会添加新的功能。)并且不能保证反斜杠转义的非特殊字符仍然有效,尽管在实践中它确实有用。
所以你可以做的最好的事情之一是:
如果您使用它突出显示已经有标记的HTML中的单词,那么您就遇到了麻烦。您的“单词”可能出现在元素名称或属性值中,在这种情况下,尝试换行&lt; B个它周围会导致破碎。在更复杂的场景中,甚至可能向XSS安全漏洞注入HTML。如果你必须应对标记,你将需要一个更复杂的方法,拆分'&lt; ...&gt;'尝试自己处理每段文本之前的标记。
答案 4 :(得分:5)
这样的事情:
if(typeof String.prototype.highlight !== 'function') {
String.prototype.highlight = function(match, spanClass) {
var pattern = new RegExp( match, "gi" );
replacement = "<span class='" + spanClass + "'>$&</span>";
return this.replace(pattern, replacement);
}
}
然后可以这样调用:
var result = "The Quick Brown Fox Jumped Over The Lazy Brown Dog".highlight("brown","text-highlight");
答案 5 :(得分:1)
对于那些患有消退或恐惧症的穷人:
function replacei(str, sub, f){
let A = str.toLowerCase().split(sub.toLowerCase());
let B = [];
let x = 0;
for (let i = 0; i < A.length; i++) {
let n = A[i].length;
B.push(str.substr(x, n));
if (i < A.length-1)
B.push(f(str.substr(x + n, sub.length)));
x += n + sub.length;
}
return B.join('');
}
s = 'Foo and FOO (and foo) are all -- Foo.'
t = replacei(s, 'Foo', sub=>'<'+sub+'>')
console.log(t)
&#13;
输出:
<Foo> and <FOO> (and <foo>) are all -- <Foo>.
答案 6 :(得分:0)
为什么不在每次调用函数时创建一个新的正则表达式?您可以使用:
new Regex([pat], [flags])
其中[pat]是模式的字符串,[flags]是标志。