Câu trả lời:
Dưới đây là cách tạo biểu thức chính quy mà không cần sử dụng cú pháp biểu thức chính quy. Điều này cho phép bạn thực hiện thao tác chuỗi tùy ý trước khi nó trở thành một đối tượng biểu thức chính quy:
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");
Nếu bạn có hai biểu thức chính quy, trên thực tế bạn có thể ghép chúng bằng kỹ thuật này:
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
Nó chỉ dài dòng hơn là chỉ có một và hai là các chuỗi theo nghĩa đen thay vì các biểu thức thông thường theo nghĩa đen.
new RegExp(/(/.source + /.*/.source + /)?/.source);
dường như không hoạt động.
expression_one
từ đâu Ý bạn là regex1
sao
Chỉ cần ngẫu nhiên ghép các đối tượng biểu thức chính quy có thể có một số tác dụng phụ bất lợi. Sử dụng RegExp.source thay thế:
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
Điều này cũng sẽ cung cấp cho bạn khả năng giữ lại các cờ biểu thức chính quy từ RegExp trước đó bằng các cờ RegExp tiêu chuẩn.
RegExp.prototype.flags
Tôi không hoàn toàn đồng ý với tùy chọn "eval".
var xxx = /abcd/;
var yyy = /efgh/;
var zzz = new RegExp(eval(xxx)+eval(yyy));
sẽ cho "// abcd // efgh //" không phải là kết quả dự định.
Sử dụng nguồn như
var zzz = new RegExp(xxx.source+yyy.source);
sẽ cho "/ abcdefgh /" và điều đó là chính xác.
Logic không cần phải ĐÁNH GIÁ, bạn biết R EX RÀNG của bạn. Bạn chỉ cần NGUỒN của nó hoặc làm thế nào nó được viết không nhất thiết là giá trị của nó. Đối với các cờ, bạn chỉ cần sử dụng đối số tùy chọn của RegExp.
Trong tình huống của tôi, tôi chạy trong vấn đề ^ và $ được sử dụng trong một số biểu thức tôi đang cố gắng kết hợp với nhau! Những biểu thức đó là các bộ lọc ngữ pháp được sử dụng trên chương trình. Bây giờ tôi sẽ không sử dụng một số trong số họ với nhau để xử lý trường hợp TRƯỚC. Tôi có thể phải "cắt" các nguồn để xóa phần bắt đầu và kết thúc ^ (và / hoặc) $ :) Chúc mừng, Alex.
var regex = "\.\..*"
Sự cố Nếu biểu thức chính quy có chứa các nhóm khớp lại như \ 1.
var r = /(a|b)\1/ // Matches aa, bb but nothing else.
var p = /(c|d)\1/ // Matches cc, dd but nothing else.
Sau đó, chỉ cần liên kết các nguồn sẽ không hoạt động. Thật vậy, sự kết hợp của hai là:
var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false
Giải pháp: Đầu tiên chúng tôi đếm số lượng nhóm phù hợp trong regex đầu tiên, sau đó với mỗi mã thông báo khớp ngược lại trong lần thứ hai, chúng tôi sẽ tăng nó theo số lượng nhóm phù hợp.
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' : ''));
}
Kiểm tra:
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; }
Nó là tốt hơn để sử dụng cú pháp bằng chữ thường xuyên nhất có thể. Nó ngắn hơn, dễ đọc hơn và bạn không cần báo giá thoát hoặc thoát ngược lại. Từ "Mô hình Javascript", Stoyan Stefanov 2010.
Nhưng sử dụng Mới có thể là cách duy nhất để nối.
Tôi sẽ tránh eval. Nó không an toàn.
Cung cấp rằng:
/this/g
hơn là new RegExp('this', 'g')
;Sau đó, bạn có thể muốn viết theo cách này:
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');
sau đó bạn có thể làm một cái gì đó như:
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>';
})
Trong trường hợp cụ thể của tôi (một trình soạn thảo giống như mã nhân bản), việc thực hiện một regex lớn sẽ dễ dàng hơn nhiều, thay vì nhiều thay thế như sau mỗi lần tôi thay thế bằng thẻ html để bọc biểu thức, mẫu tiếp theo sẽ khó khăn hơn để mục tiêu mà không ảnh hưởng đến các thẻ html bản thân (và không có lợi ích lookbehind được tiếc là không được hỗ trợ trong 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>')
Bạn có thể làm một cái gì đó như:
function concatRegex(...segments) {
return new RegExp(segments.join(''));
}
Các phân đoạn sẽ là các chuỗi (chứ không phải là regex bằng chữ) được truyền vào dưới dạng các đối số riêng biệt.
Sử dụng hàm tạo với 2 thông số và tránh sự cố với dấu '/':
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
Bạn có thể nối nguồn regex từ cả hai lớp theo nghĩa đen và RegExp:
var xxx = new RegExp(/abcd/);
var zzz = new RegExp(xxx.source + /efgh/.source);
cách dễ dàng hơn với tôi sẽ là nối các nguồn, ví dụ:
a = /\d+/
b = /\w+/
c = new RegExp(a.source + b.source)
giá trị c sẽ dẫn đến:
/ \ d + \ w + /
let regexSegment1 = String.raw`\s*hello\s*`