文字列変数を使用してその場でRegExpsを作成する


138

以下を再利用可能にしたいとします。

function replace_foo(target, replacement) {
   return target.replace("string_to_replace",replacement);
}

私はこのようなことをするかもしれません:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(string_to_replace,replacement);
}

文字列リテラルを使用すると、これは簡単です。しかし、正規表現でもう少しトリッキーにしたい場合はどうなりますか?例えば、私はすべてを交換したいと言うけど string_to_replace。本能的に私は次のようなことをすることで上記を拡張しようとします:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(/^string_to_replace/,replacement);
}

これは機能していないようです。私の推測でstring_to_replaceは、文字列を表す変数ではなく、文字列リテラルであると考えています。文字列変数を使用してその場でJavaScript正規表現を作成することは可能ですか?このような何かは、可能であれば素晴らしいでしょう:

function replace_foo(target, string_to_replace, replacement) {
   var regex = "/^" + string_to_replace + "/";
   return target.replace(regex,replacement);
}

回答:


215

ありますnew RegExp(string, flags)どこflagsですgi。そう

'GODzilla'.replace( new RegExp('god', 'i'), '' )

評価する

zilla

31
/このフォームを使用する場合も、正規表現の区切り文字を省略します。
cdhowie 2010

111

文字列リテラルを使用すると、これは簡単です。

あんまり!この例では、最初に出現するのみが置き換えられstring_to_replaceます。より一般的には、すべての出現箇所を置き換えたい場合、その場合は文字列をグローバル(/.../g)RegExp に変換する必要があります。これは、new RegExpコンストラクタを使用して文字列から実行できます。

new RegExp(string_to_replace, 'g')

これの問題は、文字列リテラルの正規表現特殊文字が通常の文字ではなく、特別な方法で動作することです。それを修正するには、バックスラッシュでエスケープする必要があります。残念ながら、これを行うための組み込み関数はありません。そのため、次の関数を使用できます。

function escapeRegExp(s) {
    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
}

また、RegExpをで使用するreplace()と、置換文字列にも特殊文字が含まれるようになり$ます。$置換テキストにリテラルを含める場合も、これをエスケープする必要があります。

function escapeSubstitute(s) {
    return s.replace(/\$/g, '$$$$');
}

$それ自体が置換文字列であるため、4つのargh!)

これで、RegExpを使用してグローバル文字列置換を実装できます。

function replace_foo(target, string_to_replace, replacement) {
    var relit= escapeRegExp(string_to_replace);
    var sub= escapeSubstitute(replacement);
    var re= new RegExp(relit, 'g');
    return target.replace(re, sub);
}

なんて痛みだ。幸いなことに、正規表現の追加部分がないストレートストリング置換だけを行う場合は、より迅速な方法があります。

s.split(string_to_replace).join(replacement)

...そしてそれがすべてです。これは一般に理解されているイディオムです。

string_to_replace以外のすべてを置き換えたいと言います

それはどういう意味ですか、あなたは文字列との一致に参加していないテキストのすべてのストレッチを置き換えたいですか?での置き換え^はこれを確実に行いません。なぜなら^、否定ではなく文字列の始まりのトークンを意味するからです。文字グループの^否定のみ[]です。否定的な先読みもありますが(?!...)、JScriptにはそれに関する問題があるため、通常は回避する必要があります。

文字列の「すべて」を照合し、関数を使用して、一致する文字列間の空のストレッチを破棄してみます。

var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')')
return target.replace(re, function(match) {
    return match[1]===''? match[2] : replacement+match[2];
});

ここでも、分割はもっと簡単かもしれません:

var parts= target.split(string_to_match);
for (var i= parts.length; i-->0;)
    if (parts[i]!=='')
        parts[i]= replacement;
return parts.join(string_to_match);

10

他の人が言ったように、new RegExp(pattern, flags)これを行うために使用します。文字列リテラルをこのコンストラクターに渡すので、すべてのバックスラッシュをエスケープする必要があることに注意してください。たとえば、正規表現をバックスラッシュに一致させたい場合は、と言う必要がありますがnew RegExp('\\\\')、正規表現リテラルはだけにする必要があります/\\/。これをどのように使用するかに応じて、適切な前処理(特殊文字のエスケープなど)をせずにユーザー入力をそのような関数に渡すことに注意する必要があります。


3
この答えは、最も詳細ではありませんが、私が1時間たった今重要な詳細について言及しています。特別なシーケンスをエスケープします。たとえば、特定の用語で始まる単語を検索していたため、必要な正規表現は/\b[term]\B/でしたが、作成するときにはを呼び出す必要がありますnew RegExp("\\b"+ term + "\\B")。小さいが重要な違いであり、正規表現として直接使用すると予想どおりに機能するため、見つけるのが困難です。
Byson


0

文字列のテキストを強調表示するための非常に良い例があると思います(レジスタを見ていないが、レジスタを使用して強調表示されていることがわかります)

function getHighlightedText(basicString, filterString) {

    if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString;

    return basicString.replace(new RegExp(filterString.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\\\$&'), 'gi'),
        function(match)
            {return "<mark>"+match+"</mark>"});

}

http://jsfiddle.net/cdbzL/1258/


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.