web-dev-qa-db-ja.com

JavaScriptの大文字と小文字を区別しない文字列置換?

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

例えば:

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

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

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

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

51

検索文字列を準備する場合、canは正規表現を使用できます。 PHPたとえば、文字列内のすべてのregex-charsをエスケープされたバージョンで置き換える関数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>" );
}
69
okoman
function highlightWords( line, Word )
{
     var regex = new RegExp( '(' + Word + ')', 'gi' );
     return line.replace( regex, "<b>$1</b>" );
}
64
tvanfosson

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>");
}
13
Tomalak

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

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

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

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

そのため、できることは次のいずれかです。

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

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

5
bobince

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

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
GitCarter

失食症または排尿困難症のある貧しい人々の場合:

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>.
1
exebook

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

new Regex([pat], [flags])

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

0
Erik Hesselink