Chuyển đổi chuỗi đầu vào của người dùng thành biểu thức chính quy


331

Tôi đang thiết kế một trình kiểm tra biểu thức chính quy trong HTML và JavaScript. Người dùng sẽ nhập regex, chuỗi và chọn chức năng họ muốn kiểm tra (ví dụ: tìm kiếm, khớp, thay thế, v.v.) thông qua nút radio và chương trình sẽ hiển thị kết quả khi chức năng đó được chạy với các đối số đã chỉ định. Đương nhiên sẽ có thêm các hộp văn bản cho các đối số bổ sung để thay thế và như vậy.

Vấn đề của tôi là nhận được chuỗi từ người dùng và biến nó thành một biểu thức thông thường. Nếu tôi nói rằng họ không cần phải có //khoảng regex họ nhập, thì họ không thể đặt cờ, như gi. Vì vậy, họ phải có //biểu thức xung quanh biểu thức, nhưng làm cách nào tôi có thể chuyển đổi chuỗi đó thành biểu thức chính quy? Nó không thể là một nghĩa đen vì nó là một chuỗi và tôi không thể chuyển nó cho hàm tạo RegExp vì nó không phải là một chuỗi mà không có chuỗi //. Có cách nào khác để biến chuỗi đầu vào của người dùng thành regex không? Tôi có phải phân tích chuỗi và cờ của biểu //thức chính quy bằng cách xây dựng nó theo cách khác không? Tôi có nên cho họ nhập một chuỗi, sau đó nhập các cờ riêng biệt không?

Câu trả lời:


609

Sử dụng hàm tạo đối tượng RegExp để tạo biểu thức chính quy từ chuỗi:

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;

1
sẽ rất tuyệt nếu có công cụ trực tuyến với trường nhập liệu
holms 14/11/13

60
Khi thực hiện theo cách này, bạn phải thoát khỏi dấu gạch chéo ngược, ví dụ:var re = new RegExp("\\w+");
JD Smith

12
@holms regex101.com cũng là một công cụ trực tuyến regex tuyệt vời
Fran Herrero

2
Phải mất một lúc tôi mới thấy rằng không có dấu gạch chéo nào được yêu cầu
Gerfried 7/12/2016

2
@JDSmith Tôi không có ý đó trong ví dụ của bạn. Tôi có nghĩa là bạn cần phải thoát khỏi dấu ngoặc kép nếu bạn muốn chúng là một phần của biểu thức chính quy với điều kiện nó được mã hóa cứng. Rõ ràng, không điều nào trong số này áp dụng nếu chuỗi nằm trong một biến như từ <input>thẻ HTML. var re = new RegExp("\"\\w+\"");là một ví dụ về regex được mã hóa cứng bằng cách sử dụng hàm tạo RegExp và việc thoát các dấu ngoặc kép cần thiết. Ý tôi là một chuỗi trong một biến là bạn chỉ có thể làm var re = new RegExp(str);strcó thể chứa dấu ngoặc kép hoặc dấu gạch chéo ngược mà không gặp vấn đề gì.
Luis Paulo

66
var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);

hoặc là

var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);

Bạn nên xem xét rằng một đầu vào không hợp lệ như /\/được công nhận.
Gumbo

8
Hoặc để hàm tạo RegExp không thành công, "trailing \ trong biểu thức chính quy", thay vì viết một trình phân tích cú pháp phức tạp.
Ẩn danh

21

Đây là một lót: str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')

Tôi đã nhận nó từ mô-đun NPM thoát chuỗi .

Dùng thử:

escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
function escapeStringRegExp(str) {
    return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
}

console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/

Sử dụng các mẫu chữ được gắn thẻ có hỗ trợ cờ:

function str2reg(flags = 'u') {
    return (...args) => new RegExp(escapeStringRegExp(evalTemplate(...args))
        , flags)
}

function evalTemplate(strings, ...values) {
    let i = 0
    return strings.reduce((str, string) => `${str}${string}${
        i < values.length ? values[i++] : ''}`, '')
}

console.log(str2reg()`example.com`)
// => /example\.com/u

15

Sử dụng hàm tạo đối tượng RegExp JavaScript .

var re = new RegExp("\\w+");
re.test("hello");

Bạn có thể truyền cờ dưới dạng đối số chuỗi thứ hai cho hàm tạo. Xem các tài liệu hướng dẫn để biết chi tiết.


9

Trong trường hợp của tôi, đầu vào của người dùng đôi khi được bao quanh bởi các dấu phân cách và đôi khi không. do đó tôi đã thêm một trường hợp khác ..

var regParts = inputstring.match(/^\/(.*?)\/([gim]*)$/);
if (regParts) {
    // the parsed pattern had delimiters and modifiers. handle them. 
    var regexp = new RegExp(regParts[1], regParts[2]);
} else {
    // we got pattern string without delimiters
    var regexp = new RegExp(inputstring);
}

3
bạn luôn có thể sử dụng .split()hàm thay vì chuỗi regex dài. regParts = inputstring.split('/')điều này sẽ tạo ra regParts[1]chuỗi regex và regParts[2]các dấu phân cách (giả sử thiết lập của regex là /.../gim). Bạn có thể kiểm tra nếu có dấu phân cách với regParts[2].length < 0.
Jaketr00

3

Tôi đề nghị bạn cũng thêm các hộp kiểm riêng hoặc trường văn bản cho các cờ đặc biệt. Theo cách đó, rõ ràng là người dùng không cần thêm bất kỳ //. Trong trường hợp thay thế, cung cấp hai trường văn bản. Điều này sẽ làm cho cuộc sống của bạn dễ dàng hơn rất nhiều.

Tại sao? Bởi vì nếu không, một số người dùng sẽ thêm //trong khi những người khác thì không. Và một số sẽ làm cho một cú pháp lỗi. Sau đó, sau khi bạn loại bỏ //, bạn có thể kết thúc bằng một biểu thức chính xác về mặt cú pháp, không giống như những gì người dùng dự định, dẫn đến hành vi lạ (từ quan điểm của người dùng).


2

Điều này cũng sẽ hoạt động khi chuỗi không hợp lệ hoặc không chứa cờ vv:

function regExpFromString(q) {
  let flags = q.replace(/.*\/([gimuy]*)$/, '$1');
  if (flags === q) flags = '';
  let pattern = (flags ? q.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1') : q);
  try { return new RegExp(pattern, flags); } catch (e) { return null; }
}

console.log(regExpFromString('\\bword\\b'));
console.log(regExpFromString('\/\\bword\\b\/gi'));
            


2

Nếu bạn thực sự muốn chuyển đổi một chuỗi thành regex, hãy thử sử dụng chức năng sau:

function String2Regex(s){return new RegExp(s.match(/\/(.+)\/.*/)[1], s.match(/\/.+\/(.*)/)[1]);}

Bạn có thể sử dụng nó như vậy:

"abc".match(String2Regex("/a/g"))
> ["a"]

Để tham khảo, đây là phiên bản được định dạng và hiện đại hơn:

const String2Regex = str => {
  // Main regex
  const main = str.match(/\/(.+)\/.*/)[1]

  // Regex options
  const options = str.match(/\/.+\/(.*)/)[1]

  // Return compiled regex
  return new RegExp(main, options)
}

1

Nhờ các câu trả lời trước đó, khối này phục vụ tốt như một giải pháp cho mục đích chung để áp dụng chuỗi có thể định cấu hình vào RegEx .. để lọc văn bản:

var permittedChars = '^a-z0-9 _,.?!@+<>';
permittedChars = '[' + permittedChars + ']';

var flags = 'gi';
var strFilterRegEx = new RegExp(permittedChars, flags);

log.debug ('strFilterRegEx: ' + strFilterRegEx);

strVal = strVal.replace(strFilterRegEx, '');
// this replaces hard code solt:
// strVal = strVal.replace(/[^a-z0-9 _,.?!@+]/ig, '');

1

Bạn có thể yêu cầu cờ sử dụng các hộp kiểm sau đó làm một cái gì đó như thế này:

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);

trông giống như RegEx thiếu dấu p .. stack sẽ không cho phép tôi thực hiện chỉnh sửa 1 nhân vật
Gene Bo

-3

Tôi sử dụng evalđể giải quyết vấn đề này.

Ví dụ:

    function regex_exec() {

        // Important! Like @Samuel Faure mentioned, Eval on user input is a crazy security risk, so before use this method, please take care of the security risk. 
        var regex = $("#regex").val();

        // eval()
        var patt = eval(userInput);

        $("#result").val(patt.exec($("#textContent").val()));
    }

3
eval trên userInput là một rủi ro bảo mật điên rồ
Samuel Faure

1
mr bgie bảng!
Luiz Felipe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.