回答:
正規表現リテラル構文を使用せずに正規表現を作成する方法は次のとおりです。これにより、正規表現オブジェクトになる前に任意の文字列操作を行うことができます。
var segment_part = "some bit of the regexp";
var pattern = new RegExp("some regex segment" + /*comment here */
segment_part + /* that was defined just now */
"another segment");
2つの正規表現リテラルがある場合、実際には次の手法を使用してそれらを連結できます。
var regex1 = /foo/g;
var regex2 = /bar/y;
var flags = (regex1.flags + regex2.flags).split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
var regex3 = new RegExp(expression_one.source + expression_two.source, flags);
// regex3 is now /foobar/gy
それは、式1と2がリテラル正規表現ではなくリテラル文字列であることだけではなく、より多くの意味を持ちます。
new RegExp(/(/.source + /.*/.source + /)?/.source);
しないようです。
expression_one
から来たの?もしかしてregex1
?
正規表現オブジェクトをランダムに連結するだけでは、いくつかの悪影響があります。代わりにRegExp.sourceを使用します。
var r1 = /abc/g;
var r2 = /def/;
var r3 = new RegExp(r1.source + r2.source,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '') +
(r1.multiline ? 'm' : ''));
console.log(r3);
var m = 'test that abcdef and abcdef has a match?'.match(r3);
console.log(m);
// m should contain 2 matches
これにより、標準のRegExpフラグを使用して、以前のRegExpの正規表現フラグを保持することもできます。
RegExp.prototype.flags
「eval」オプションに同意しません。
var xxx = /abcd/;
var yyy = /efgh/;
var zzz = new RegExp(eval(xxx)+eval(yyy));
「// abcd // efgh //」は意図した結果ではありません。
のようなソースを使用する
var zzz = new RegExp(xxx.source+yyy.source);
「/ abcdefgh /」が表示されますが、これは正しいです。
論理的には評価する必要はありません、あなたはあなたの表現を知っています。あなたはそのソースまたはそれがどのように書かれているかが必要なだけで、必ずしもその値ではありません。フラグについては、RegExpのオプションの引数を使用するだけです。
私の状況では、^と$を一緒に連結しようとしているいくつかの式で使用されているという問題が発生します!これらの式は、プログラム全体で使用される文法フィルターです。今、私はそれらのいくつかを一緒に使用して、事前配置のケースを処理したくありません。最初と最後の^(または)$ :)を削除するために、ソースを「スライス」する必要があるかもしれません。乾杯、アレックス。
var regex = "\.\..*"
問題正規表現に\ 1のようなバックマッチンググループが含まれている場合。
var r = /(a|b)\1/ // Matches aa, bb but nothing else.
var p = /(c|d)\1/ // Matches cc, dd but nothing else.
次に、汚染源を汚染するだけでは機能しません。実際、この2つの組み合わせは次のとおりです。
var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false
解決策: 最初に、最初の正規表現で一致するグループの数を数えます。次に、2番目の一致する各トークンについて、一致するグループの数だけトークンをインクリメントします。
function concatenate(r1, r2) {
var count = function(r, str) {
return str.match(r).length;
}
var numberGroups = /([^\\]|^)(?=\((?!\?:))/g; // Home-made regexp to count groups.
var offset = count(numberGroups, r1.source);
var escapedMatch = /[\\](?:(\d+)|.)/g; // Home-made regexp for escaped literals, greedy on numbers.
var r2newSource = r2.source.replace(escapedMatch, function(match, number) { return number?"\\"+(number-0+offset):match; });
return new RegExp(r1.source+r2newSource,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '')
+ (r1.multiline ? 'm' : ''));
}
テスト:
var rp = concatenate(r, p) // returns /(a|b)\1(c|d)\2/
rp.test("aadd") // Returns true
function concatenateList() { var res = arguments[0]; for(var i = 1; i < arguments.length; i++) { res = concatenate(res, arguments[i]); } return res; }
それを提供する:
/this/g
よりもnew RegExp('this', 'g')
、次に、次のように記述します。
var regexParts =
[
/\b(\d+|null)\b/,// Some comments.
/\b(true|false)\b/,
/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|length|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/,
/(\$|jQuery)/,
/many more patterns/
],
regexString = regexParts.map(function(x){return x.source}).join('|'),
regexPattern = new RegExp(regexString, 'g');
その後、次のようなことができます:
string.replace(regexPattern, function()
{
var m = arguments,
Class = '';
switch(true)
{
// Numbers and 'null'.
case (Boolean)(m[1]):
m = m[1];
Class = 'number';
break;
// True or False.
case (Boolean)(m[2]):
m = m[2];
Class = 'bool';
break;
// True or False.
case (Boolean)(m[3]):
m = m[3];
Class = 'keyword';
break;
// $ or 'jQuery'.
case (Boolean)(m[4]):
m = m[4];
Class = 'dollar';
break;
// More cases...
}
return '<span class="' + Class + '">' + m + '</span>';
})
私の特定のケース(コードミラーのようなエディター)では、次のような多くの置換を行うよりも、1つの大きな正規表現を実行する方がはるかに簡単です。 htmlタグ自体に影響を与えずに(そして残念ながらJavaScriptではサポートされていない後戻りなしに)ターゲットに設定するのは困難です。
.replace(/(\b\d+|null\b)/g, '<span class="number">$1</span>')
.replace(/(\btrue|false\b)/g, '<span class="bool">$1</span>')
.replace(/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/g, '<span class="keyword">$1</span>')
.replace(/\$/g, '<span class="dollar">$</span>')
.replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation">$1</span>')
2つのパラメーターを持つコンストラクターを使用し、末尾の「/」の問題を回避します。
var re_final = new RegExp("\\" + ".", "g"); // constructor can have 2 params!
console.log("...finally".replace(re_final, "!") + "\n" + re_final +
" works as expected..."); // !!!finally works as expected
// meanwhile
re_final = new RegExp("\\" + "." + "g"); // appends final '/'
console.log("... finally".replace(re_final, "!")); // ...finally
console.log(re_final, "does not work!"); // does not work
let regexSegment1 = String.raw`\s*hello\s*`