Замена строки без учета регистра в JavaScript?
мне нужно выделить, без учета регистра, данные ключевые слова в строке JavaScript.
например:
-
highlight("foobar Foo bar FOO", "foo")
должен возвратить"<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"
мне нужен код для работы с любым ключевым словом и, следовательно, с помощью жестко закодированного регулярного выражения, такого как /foo/i
не является достаточным решением.
какой самый простой способ сделать это?
(Это пример более общей проблемы, подробно описанной в названии, но я чувствую, что лучше всего обратиться к конкретному, полезному примеру.)
7 ответов
вы can используйте регулярные выражения при подготовке строки поиска. В PHP, например, есть функция preg_quote, которая заменяет все regex-символы в строке их экранированными версиями.
вот такая функция для 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("");
// * returns 1: '$40'
// * example 2: preg_quote("*RRRING* Hello?");
// * returns 2: '\*RRRING\* Hello\?'
// * example 3: preg_quote("\.+*?[^]$(){}=!<>|:");
// * returns 3: '\\.\+\*\?\[\^\]$\(\)\{\}\=\!\<\>\|\:'
return (str+'').replace(/([\\.\+\*\?\[\^\]$\(\)\{\}\=\!\<\>\|\:])/g, "\");
}
(взято из 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></b>" );
}
function highlightWords( line, word )
{
var regex = new RegExp( '(' + word + ')', 'gi' );
return line.replace( regex, "<b></b>" );
}
вы можете улучшить объект 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></b>");
}
регулярные выражения хороши, пока ключевые слова действительно слова, вы можете просто использовать конструктор RegExp вместо литерала для создания одного из переменных:
var re= new RegExp('('+word+')', 'gi');
return s.replace(re, '<b></b>');
трудность возникает, если "ключевые слова" могут иметь пунктуацию, поскольку пунктуация имеет особое значение в регулярных выражениях. К сожалению, в отличие от большинства других языков/библиотек с поддержкой regexp, в JavaScript нет стандартной функции для избежания пунктации для регулярных выражений.
и вы не можете быть полностью уверен, что именно символы нуждаются в экранировании, потому что не каждая реализация браузера regexp гарантированно будет точно такой же. (В частности, новые браузеры могут добавлять новые функции.) И обратные косые черты-экранирующие символы, которые не являются особенными, не гарантируют, что все еще будут работать, хотя на практике это происходит.
Так что лучшее, что вы можете сделать, это один из:
- попытка поймать каждый специальный символ в общем браузере использовать сегодня [add: see Sebastian's рецепт]
- обратная косая черта-избежать всех не буквенно-цифровых. care: \W также будет соответствовать символам Unicode не ASCII, которые вы действительно не хотите.
- просто убедитесь, что в ключевом слове нет не буквенно-цифровых символов перед поиском
Если вы используете это, чтобы выделить слова в HTML, который уже имеет разметку, хотя, у вас есть проблемы. Ваше " слово’ может отображаться в имени элемента или значении атрибута, и в этом случае попытка обернуть вокруг него 'разметка перед попыткой обработать каждый участок текста самостоятельно.
Как насчет чего-то вроде этого:
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");
для тех бедных с disregexia или regexophobia:
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)
выход:
<Foo> and <FOO> (and <foo>) are all -- <Foo>.
почему бы просто не создать новое регулярное выражение при каждом вызове функции? Вы можете использовать:
new Regex([pat], [flags])
где [pat] - строка для шаблона, а [flags] - флаги.