Я просто хочу создать регулярное выражение из любой возможной строки.
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
Есть ли встроенный метод для этого? Если нет, что люди используют? Ruby имеет RegExp.escape
. Я не чувствую, что мне нужно написать свое, там должно быть что-то стандартное. Спасибо!
Недопустимая функция, связанная выше. Он не может выйти из ^
или $
(начало и конец строки) или -
, которое в группе символов используется для диапазонов.
Используйте эту функцию:
RegExp.escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
Хотя на первый взгляд это может показаться излишним, экранирование -
(а также ^
) делает функцию, подходящую для экранирования символов, вставляться в класс символов, а также тело регулярного выражения.
Escaping /
делает функцию, подходящую для экранирующих символов, использоваться в литературе JS regex для последующего eval.
Поскольку нет недостатков, чтобы избежать любого из них, имеет смысл убежать, чтобы охватить более широкие варианты использования.
И да, это разочаровывает неудача, что это не часть стандартного JavaScript.
$&
делать?
Для тех, кто использует lodash, с версии v3.0.0, функция _. escapeRegExp встроена:
_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'
И если вам не нужна полная библиотека lodash, вам может потребоваться только эта функция!
Большинство выражений здесь описывают отдельные конкретные варианты использования.
Это хорошо, но я предпочитаю подход "всегда работает".
function regExpEscape(literal_string) {
return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}
Это будет "полностью избежать" буквальной строки для любого из следующих применений в регулярных выражениях:
new RegExp(regExpEscape(str))
new RegExp('[' + regExpEscape(str) + ']')
new RegExp('x{1,' + regExpEscape(str) + '}')
Специальные символы:
-
: Создает диапазон символов в классе символов.[
/]
: Запускает/завершает класс символов.{
/}
: Запускает/завершает спецификатор нумерации.(
/)
: Запускает/завершает группу.*
/+
/?
: указывает тип повторения..
: соответствует любому символу.\
: стирает символы и запускает объекты.^
: Задает начало зоны соответствия и отменяет соответствие в классе символов.$
: Задает конец зоны соответствия.|
: Указывает чередование.#
: указывает комментарий в режиме свободного интервала.\s
: Игнорируется в режиме свободного интервала.,
: разделяет значения в спецификаторе нумерации./
: начинает или завершает выражение.:
: Завершает специальные типы групп и часть классов символов в стиле Perl.!
: Отменяет группу нулевой ширины.<
/=
: Часть спецификаций группы нулевой ширины.Примечания:
/
не является строго необходимым в любом вкусе регулярного выражения. Тем не менее, он защищает, если кто-то (дрожь) делает eval("/" + pattern + "/");
.,
гарантирует, что если строка должна быть целым числом в числовом спецификаторе, она будет корректно вызывать ошибку компиляции RegExp вместо того, чтобы молча выполнять компиляцию.#
и \s
не нужно бежать в JavaScript, но делать это во многих других вариантах. Они сбегают здесь, если регулярное выражение будет передано в другую программу.Если вам также необходимо проверять будущее регулярное выражение от возможных дополнений к возможностям JavaScript-регекса JavaScript, я рекомендую использовать более параноидальный:
function regExpEscapeFuture(literal_string) {
return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}
Эта функция пропускает каждый символ, за исключением тех, которые явно гарантированно не используются для синтаксиса в будущих ароматах регулярных выражений.
Для истинной санитарии рассмотрите этот краевой случай:
var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');
Это должно хорошо компилироваться в JavaScript, но не будет в некоторых других вариантах. Если намереваться передать другой вкус, нулевой случай s === ''
должен быть независимо проверен, например:
var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');
/
Не нужно экранировать в [...]
символьном классе.
В виджетах jQueryUI autocomplete (версия 1.9.1) они используют немного другое регулярное выражение (строка 6753), здесь это регулярное выражение в сочетании с подходом @bobince.
RegExp.escape = function( value ) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
,
(который не метасимволом) и #
и пробелы , которые только материя в режиме свободного расстояния (который не поддерживается JavaScript). Тем не менее, они понимают это правильно, чтобы не избежать косой черты.
$.ui.autocomplete.escapeRegex(myString)
.
Руководство по регулярным выражениям для Mozilla Developer Network предоставляет следующую функцию:
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
=
? AFAIK, это было бы полезно для регулярных выражений в Perl ( ?=
), Но если вы избежите ?
ты в порядке.
=
больше не включена.
Ничто не должно препятствовать простому экранированию каждого не-буквенно-цифрового символа:
usersString.replace(/(?=\W)/g, '\\');
Вы теряете определенную степень удобочитаемости при выполнении re.toString()
, но вы выигрываете большую простоту (и безопасность).
В соответствии с ECMA-262, с одной стороны, регулярные выражения "синтаксические символы" всегда не являются алфавитно-цифровыми, так что результат является безопасным, а специальные escape-последовательности (\d
, \w
, \n
) всегда являются буквенно-цифровыми, так что не будут выдаваться ложные контрольные экраны.
.replace(/[^\w]/g, '\\$&')
будет работать таким же образом.
.replace(/\W/g, "\\$&");
Существует предложение ES7 для RegExp.escape в https://github.com/benjamingr/RexExp.escape/, а polyfill доступно https://github.com/ljharb/regexp.escape.
Это более короткая версия.
RegExp.escape = function(s) {
return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}
Это включает неметаные символы %
, &
, '
и ,
, но спецификация JavaScript RegExp позволяет это.
escapeRegExp = function(str) {
if (str == null) return '';
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
I Googled для онлайн-инструмента, который сделает это, но на удивление не смог найти его. Мог бы обернуться, чтобы однажды сбить кого-то, чтобы заткнуть промежуток, но в то же время сделал простой скрипт JS из принятого ответа:
https://jsfiddle.net/xnd0bkne/
StackOverflow требует, чтобы код был опубликован для скрипта JS, так что вот оно:
var s = prompt("Enter text to be REGEX-ESCAPED: ");
prompt("REGEX-ESCAPED (please select and copy the text below): ",
s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
Вместо того, чтобы избегать символов, которые могут вызвать проблемы в вашем регулярном выражении (например, черный список), почему бы не использовать вместо этого белый список. Таким образом, каждый символ считается испорченным, если он не соответствует.
В этом примере предположим следующее выражение:
RegExp.escape('be || ! be');
Это белый список букв, цифр и пробелов:
RegExp.escape = function (string) {
return string.replace(/([^\w\d\s])/gi, '\\$1');
}
Возврат:
"be \|\| \! be"
Это может ускользнуть от символов, которые не должны быть экранированы, но это не мешает вашему выражению (возможно, незначительные штрафные санкции - но это того стоит для безопасности).
XRegExp имеет функцию escape:
XRegExp.escape('Escaped? <.>');
// -> 'Escaped\?\ <\.>'
Подробнее: http://xregexp.com/api/#escape
Функции в других ответах являются излишними для экранирования всех регулярных выражений (они могут быть полезны для экранирования частей регулярных выражений, которые позже будут объединены в большие регулярные выражения).
Если вы избегаете всего регулярного выражения и выполняетесь с ним, цитируя метасимволы, которые являются автономными (.
, ?
, +
, *
, ^
, $
, |
, \
) или начать что-то ((
, [
, {
) - все, что вам нужно:
String.prototype.regexEscape = function regexEscape() {
return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};
И да, это разочаровывает, что JavaScript не имеет такой функции, как этот встроенный.
(text)next
и вставляете его в: (?:
+ Input + )
. Ваш метод выдаст результирующую строку (?:\(text)next)
которая не скомпилируется. Обратите внимание, что это вполне разумная вставка, а не какая-то сумасшедшая, например re\
+ input + re
(в этом случае программиста можно обвинить в том, что он сделал глупость)
RegExp.escape
вам, что заRegExp.escape
в настоящее время работает, и любой, кто думает, что у них есть ценный вклад, можетRegExp.escape
. core-js и другие polyfills предлагают это.