54

JavaScript文字列内の特定のキーワードを、大文字と小文字を区別せずに強調表示する必要があります。

例えば:

  • highlight("foobar Foo bar FOO", "foo")戻る必要があります"<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"

どのキーワードでも機能するコードが必要なので、のようなハードコードされた正規表現を使用する/foo/iだけでは十分な解決策ではありません。

これを行う最も簡単な方法は何ですか?

(これは、タイトルで詳しく説明されているより一般的な問題の例ですが、具体的で有用な例で取り組むのが最善だと思います。)

4

7 に答える 7

72

検索文字列を用意すれば、正規表現を使用できます。たとえば、PHP には関数 preg_quote があり、文字列内のすべての正規表現文字をエスケープされたバージョンに置き換えます。

これは、javascript ( source )の関数です。

function preg_quote (str, delimiter) {
  //  discuss at: https://locutus.io/php/preg_quote/
  // original by: booeyOH
  // improved by: Ates Goral (https://magnetiq.com)
  // improved by: Kevin van Zonneveld (https://kvz.io)
  // improved by: Brett Zamir (https://brett-zamir.me)
  // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
  //   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(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&')
}

したがって、次のことができます。

function highlight(str, search) {
    return str.replace(new RegExp("(" + preg_quote(search) + ")", 'gi'), "<b>$1</b>");
}
于 2008-11-11T12:54:48.690 に答える
64
function highlightWords( line, word )
{
     var regex = new RegExp( '(' + word + ')', 'gi' );
     return line.replace( regex, "<b>$1</b>" );
}
于 2008-11-11T13:06:44.033 に答える
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>");
}
于 2008-11-11T14:07:47.717 に答える
6

このようなものはどうですか:

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");
于 2012-09-14T20:00:26.270 に答える
6

正規表現は、キーワードが実際に単語である限り問題ありません。リテラルの代わりに RegExp コンストラクターを使用して、変数から作成することができます。

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

句読点は正規表現で特別な意味を持つ傾向があるため、「キーワード」に句読点を含めることができる場合、問題が発生します。残念ながら、正規表現をサポートする他のほとんどの言語/ライブラリとは異なり、JavaScript には正規表現の句読点をエスケープする標準関数はありません。

また、すべてのブラウザーの正規表現の実装がまったく同じであることが保証されているわけではないため、どの文字をエスケープする必要があるかを正確に把握することはできません。(特に、新しいブラウザーでは新しい機能が追加される可能性があります。) また、特別ではないバックスラッシュ エスケープ文字は、実際には機能しますが、機能することが保証されていません。

したがって、あなたができる最善のことは、次のいずれかです。

  • 今日一般的なブラウザで使用されている各特殊文字をキャッチしようとしています [追加: Sebastian のレシピを参照してください]
  • 英数字以外はすべてバックスラッシュでエスケープします。注意: \W は非 ASCII Unicode 文字にも一致しますが、これはあまり望ましくありません。
  • 検索する前に、キーワードに英数字以外が含まれていないことを確認してください

ただし、既にマークアップが含まれている HTML 内の単語を強調表示するためにこれを使用している場合は、問題が発生します。あなたの「単語」は要素名または属性値に現れるかもしれません。その場合、それを < b> で囲もうとすると壊れてしまいます。より複雑なシナリオでは、XSS セキュリティ ホールへの HTML インジェクションでさえある可能性があります。マークアップに対処する必要がある場合は、'< を分割する、より複雑なアプローチが必要になります。... >' マークアップしてから、テキストの各ストレッチを独自に処理しようとします。

于 2008-11-11T13:15:49.757 に答える
0

関数を呼び出すたびに新しい正規表現を作成しないのはなぜですか? 以下を使用できます。

new Regex([pat], [flags])

[pat] はパターンの文字列で、[flags] はフラグです。

于 2008-11-11T12:59:41.317 に答える