Замена строки без учета регистра в JavaScript?

Мне нужно выделить, без учета регистра, заданные ключевые слова в строке JavaScript.

Например:

  • highlight("foobar Foo bar FOO", "foo") должен вернуть "foobar Foo bar FOO"

Мне нужен код для работы с любым ключевым словом, и поэтому использование жестко закодированного регулярного выражения, такого как /foo/i, не является достаточным решением.

Какой самый простой способ сделать это?

(Это пример более общей проблемы, подробно изложенной в заголовке, но я чувствую, что лучше рассмотреть конкретный, полезный пример. )

вопрос задан 11.11.2008
inspite
14584 репутация

7 ответов


  • 69 рейтинг

    Вы можете использовать регулярные выражения, если вы готовите строку поиска. В PHP e. г. есть функция 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' ), "$1" );
    }
    
    ответ дан okoman, с репутацией 3568, 11.11.2008
  • 64 рейтинг
    function highlightWords( line, word )
    {
         var regex = new RegExp( '(' + word + ')', 'gi' );
         return line.replace( regex, "$1" );
    }
    
    ответ дан tvanfosson, с репутацией 416703, 11.11.2008
  • 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, "$1");
    }
    
    ответ дан Tomalak, с репутацией 251122, 11.11.2008
  • 5 рейтинг

    Регулярные выражения хороши, если ключевые слова действительно являются словами, вы можете просто использовать конструктор RegExp вместо литерала, чтобы создать его из переменной:

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

    Трудность возникает, если в «ключевых словах» может быть пунктуация, поскольку в регулярных выражениях пунктуация имеет особое значение. К сожалению, в отличие от большинства других языков / библиотек с поддержкой регулярных выражений, в JavaScript нет стандартной функции, позволяющей избежать пунктуации для регулярных выражений.

    И вы не можете быть полностью уверены, какие именно символы должны быть экранированы, потому что не каждая реализация regexp в браузере гарантированно будет одинаковой. (В частности, новые браузеры могут добавлять новые функции. ) И символы, не являющиеся специальными, без обратной косой черты не гарантируют, что все еще работают, хотя на практике это работает.

    Итак, самое лучшее, что вы можете сделать, это одно из:

    • пытается поймать каждый специальный символ в обычном браузерном использовании сегодня [добавить: см. Рецепт Себастьяна]
    • обратный слеш-экранирование всех не алфавитно-цифровых символов. care: \ W также будет соответствовать не-ASCII символам Unicode, которые вам не нужны.
    • просто убедитесь, что в ключевом слове нет никаких буквенно-цифровых символов перед поиском

    Если вы используете это для выделения слов в HTML, которые уже содержат разметку, у вас возникнут проблемы. Ваше «слово» может появиться в имени элемента или в значении атрибута, и в этом случае при попытке обернуть & lt; б & GT; вокруг это приведет к поломке. В более сложных сценариях возможно даже HTML-инъекция в дыру в безопасности XSS. Если вам нужно справиться с разметкой, вам понадобится более сложный подход, разделив ‘& lt; , , , Разметка & gt; перед попыткой обработать каждый фрагмент текста самостоятельно.

    ответ дан bobince, с репутацией 433365, 11.11.2008
  • 5 рейтинг

    Что-то вроде этого:

    if(typeof String.prototype.highlight !== 'function') {
      String.prototype.highlight = function(match, spanClass) {
        var pattern = new RegExp( match, "gi" );
        replacement = "$&";
    
        return this.replace(pattern, replacement);
      }
    }
    

    Это можно было бы назвать так:

    var result = "The Quick Brown Fox Jumped Over The Lazy Brown Dog".highlight("brown","text-highlight");
    
    ответ дан GitCarter, с репутацией 112, 14.09.2012
  • 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)

    Выход:

     and  (and ) are all -- .
    
    ответ дан exebook, с репутацией 12557, 14.02.2017
  • 0 рейтинг

    Почему бы просто не создавать новое регулярное выражение при каждом вызове вашей функции? Вы можете использовать:

    new Regex([pat], [flags])
    

    где [pat] - строка для шаблона, а [flags] - флаги.

    ответ дан Erik Hesselink, с репутацией 2051, 11.11.2008