Преобразование пользовательской строки ввода в регулярное выражение

215

Я разрабатываю тестер регулярных выражений в HTML и JavaScript. Пользователь вводит регулярное выражение, строку и выбирает функцию, которую они хотят протестировать (например, поиск, совпадение, замена и т.д.) С помощью переключателя, и программа отображает результаты, когда эта функция запускается с указанными аргументами. Естественно, будут дополнительные текстовые поля для дополнительных аргументов для замены и т.д.

Моя проблема - получить строку от пользователя и превратить ее в регулярное выражение. Если я скажу, что им не нужно иметь // вокруг регулярного выражения, которое они вводят, то они не могут устанавливать флаги, такие как g и i. Поэтому они должны иметь // вокруг выражения, но как я могу преобразовать эту строку в регулярное выражение? Он не может быть литералом с его строки, и я не могу передать его конструктору RegExp, так как он не является строкой без //. Есть ли другой способ сделать строку ввода пользователя в регулярное выражение? Должен ли я проанализировать строку и флаги регулярного выражения с помощью //, а затем построить его другим способом? Должен ли я им вводить строку, а затем вводить флаги отдельно?

Теги:

9 ответов

399
Лучший ответ

Используйте конструктор объектов RegExp, чтобы создать регулярное выражение из строки:

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;
  • 1
    было бы неплохо иметь онлайн инструмент с полем ввода
  • 49
    Делая это таким образом, вы должны избегать обратной косой черты, например, var re = new RegExp("\\w+");
Показать ещё 8 комментариев
51
var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);

или

var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);
  • 0
    Вам следует учитывать, что неверный ввод, такой как /\/ , распознается.
  • 6
    Или позволить конструктору RegExp завершиться с ошибкой, "завершая \ в регулярном выражении", вместо написания сложного синтаксического анализатора.
Показать ещё 2 комментария
8

Используйте конструктор JavaScript RegExp.

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

Вы можете передавать флаги в качестве второго строкового аргумента конструктору. Подробнее см. В документации.

7

Вот один слой: str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')

Я получил его из модуля escape-string-regexp NPM.

Попытка:

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

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

В моем случае пользовательский ввод некогда был окружен разделителями, а иногда и нет. поэтому я добавил другой случай..

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);
}
  • 2
    вы всегда можете использовать .split() вместо длинной строки регулярного выражения. regParts = inputstring.split('/') это сделает regParts[1] строкой регулярных выражений, а regParts[2] разделителями (при условии, что настройкой регулярного выражения является /.../gim ). Вы можете проверить, есть ли разделители с regParts[2].length < 0 .
2

Я предлагаю вам также добавить отдельные флажки или текстовое поле для специальных флагов. Таким образом, понятно, что пользователю не нужно добавлять никаких //. В случае замены укажите два текстовых поля. Это сделает вашу жизнь намного легче.

Почему? Потому что в противном случае некоторые пользователи добавят //, а другие - нет. И некоторые будут делать синтаксическую ошибку. Затем, после того, как вы разделили //, вы можете получить синтаксически действующее регулярное выражение, которое не похоже на то, что предназначалось пользователю, что приводит к странному поведению (с точки зрения пользователя).

1

Это будет работать также, когда строка недействительна или не содержит флагов и т.д.:

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'));
            
1

Благодаря более ранним ответам эти блоки служат также универсальным решением для применения настраиваемой строки в RegEx.. для фильтрации текста:

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, '');
0

Вы можете запросить флаги с помощью флажков, а затем сделать что-то вроде этого:

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);
  • 0
    Похоже, что в RegEx отсутствует конечная буква p . Стек не позволяет мне редактировать 1 символ

Ещё вопросы

Сообщество Overcoder
Наверх
Меню