Преобразование пользовательской строки ввода в регулярное выражение - PullRequest
304 голосов
/ 17 мая 2009

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

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

Ответы [ 10 ]

562 голосов
/ 17 мая 2009

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

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;
62 голосов
/ 17 мая 2009
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]);
14 голосов
/ 18 февраля 2016

Вот одна строка: 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/
13 голосов
/ 17 мая 2009

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

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

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

9 голосов
/ 31 марта 2014

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

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 голосов
/ 09 сентября 2016

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

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 голосов
/ 17 мая 2009

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

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

1 голос
/ 21 сентября 2015

Благодаря более ранним ответам, эти блоки служат хорошим решением для применения настраиваемой строки в 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 голосов
/ 20 марта 2019

Если вы действительно хотите преобразовать строку в регулярное выражение, попробуйте использовать следующую функцию:

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

Вы можете использовать его так:

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

Для справки, вот отформатированная и более современная версия:

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)
}
0 голосов
/ 17 мая 2009

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

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...