JavaScript中不区分大小写的字符串替换?

时间:2008-11-11 12:49:02

标签: javascript string replace case-insensitive

在JavaScript字符串中给出关键字时,我需要强调不区分大小写。

例如:

  • highlight("foobar Foo bar FOO", "foo")应该返回"<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"

我需要代码适用于任何关键字,因此使用像/foo/i这样的硬编码正则表达式并不是一个充分的解决方案。

最简单的方法是什么?

(这是标题中详述的更一般问题的一个实例,但我觉得最好用一个具体,有用的例子来解决。)

7 个答案:

答案 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实现都保证完全相同。 (特别是,较新的浏览器可能会添加新的功能。)并且不能保证反斜杠转义的非特殊字符仍然有效,尽管在实践中它确实有用。

所以你可以做的最好的事情之一是:

  • 尝试在今天常见的浏览器中使用每个特殊字符[添加:请参阅Sebastian的配方]
  • 反斜杠 - 逃避所有非字母数字。 care:\ W还将匹配您不想要的非ASCII Unicode字符。
  • 确保在搜索
  • 之前,关键字中没有非字母数字

如果您使用它突出显示已经有标记的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)

对于那些患有消退或恐惧症的穷人:

&#13;
&#13;
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;
&#13;
&#13;

输出:

<Foo> and <FOO> (and <foo>) are all -- <Foo>.

答案 6 :(得分:0)

为什么不在每次调用函数时创建一个新的正则表达式?您可以使用:

new Regex([pat], [flags])

其中[pat]是模式的字符串,[flags]是标志。