JavaScript中不区分大小写的stringreplace?

我需要突出显示,不区分大小写,给定JavaScriptstring中的关键字。

例如:

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

我需要代码来处理任何关键字,因此使用像/foo/i这样的硬编码正则expression式不是一个足够的解决scheme。

什么是最简单的方法来做到这一点?

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

如果您准备searchstring,则可以使用正则expression式。 在PHP中,例如有一个函数preg_quote,它用它们的转义版本replacestring中的所有正则expression式字符。

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/

所以你coudl做以下几点:

 function highlight( data, search ) { return data.replace( new RegExp( "(" + preg_quote( search ) + ")" , 'gi' ), "<b>$1</b>" ); } 
 function highlightWords( line, word ) { var regex = new RegExp( '(' + word + ')', 'gi' ); return line.replace( regex, "<b>$1</b>" ); } 

您可以使用为您特殊字符转义的函数来增强RegExp对象:

 RegExp.escape = function(str) { var specials = /[.*+?|()\[\]{}\\$^]/g; // .*+?|()[]{}\$^ return str.replace(specials, "\\$&"); } 

那么你可以使用别人的build议而不用担心:

 function highlightWordsNoCase(line, word) { var regex = new RegExp("(" + RegExp.escape(word) + ")", "gi"); return line.replace(regex, "<b>$1</b>"); } 

只要关键字是单词,正则expression式就可以了,您可以使用RegExp构造函数而不是文字从variables创build一个:

 var re= new RegExp('('+word+')', 'gi'); return s.replace(re, '<b>$1</b>'); 

如果“关键词”在标点符号中可能有标点符号,那么困难就会出现,因为标点符号往往在正则expression式中有特殊的含义。 不幸的是,与大多数支持正则expression式的其他语言/库不同,没有标准的函数来避免JavaScript中正则expression式的标点符号。

而且不能完全确定哪些字符需要转义,因为并不是每个浏览器的regexp实现都是完全一样的。 (特别是较新的浏览器可能会添加新的function。)并不是特殊的反斜杠转义字符不能保证能够正常工作,尽pipe在实践中它确实有效。

所以最好你可以做的是:

  • 试图抓住今天常用浏览器中的每个特殊字符[add:see Sebastian's recipe]
  • 反斜杠 – 转义所有非字母数字。 注意:\ W也将匹配非ASCII的Unicode字符,你不是真的想要。
  • 只要确保search之前关键字中没有非字母数字

如果你用这个来突出HTML中已经有标记的单词,那么你遇到了麻烦。 您的“单词”可能出现在元素名称或属性值中,在这种情况下尝试在其周围包裹<b>将导致破碎。 在更复杂的情况下,甚至可能将HTML注入到XSS安全漏洞。 如果你必须应付标记,你将需要一个更复杂的方法,在试图自行处理每一段文本之前,先分开'<…>'标记。

那么这样的事情呢?

 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"); 

对于那些不喜欢或反悔的人:

 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) 

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

 new Regex([pat], [flags]) 

其中[pat]是模式的string,[flags]是标志。