Есть ли функция RegExp.escape в Javascript? - PullRequest
374 голосов
/ 25 августа 2010

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

var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);

Есть ли встроенный метод для этого?Если нет, что люди используют?Рубин имеет RegExp.escape.Я не чувствую, что мне нужно писать свое, должно быть что-то стандартное.Спасибо!

Ответы [ 12 ]

490 голосов
/ 25 августа 2010

Функция, связанная выше, недостаточна. Он не может экранировать ^ или $ (начало и конец строки) или -, который в группе символов используется для диапазонов.

Используйте эту функцию:

RegExp.escape= function(s) {
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};

Хотя на первый взгляд это может показаться ненужным, экранирование - (а также ^) делает функцию подходящей для экранирования символов, которые будут вставлены в класс символов, а также в тело регулярного выражения.

Escaping / делает функцию подходящей для экранирования символов, которые будут использоваться в литерале регулярного выражения JS для последующего вычисления.

Так как нет побочных эффектов для побега, имеет смысл сбежать, чтобы охватить более широкие варианты использования.

И да, досадно, что это не является частью стандартного JavaScript.

88 голосов
/ 17 апреля 2015

Для тех, кто использует lodash, начиная с версии 3.0.0 * _. EscapeRegExp встроена функция:

_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'

И в случае, если выне хотите требовать полной библиотеки lodash, вам может потребоваться только эта функция !

36 голосов
/ 15 июня 2015

Большинство выражений здесь решают единичные конкретные случаи использования.

Это нормально, но я предпочитаю подход "всегда работает".

function regExpEscape(literal_string) {
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

Это будет "полностью экранировать" литералСтрока для любого из следующих применений в регулярных выражениях:

  • Вставка в регулярное выражение.Например, new RegExp(regExpEscape(str))
  • Вставка в класс символов.Например, new RegExp('[' + regExpEscape(str) + ']')
  • Вставка в спецификатор целого числа.Например, new RegExp('x{1,' + regExpEscape(str) + '}')
  • Выполнение в механизмах регулярных выражений, отличных от JavaScript.

Охватываемые специальные символы:

  • -: создание диапазона символов вкласс символов.
  • [ / ]: запуск / окончание класса символов.
  • { / }: запуск / окончание спецификатора нумерации.
  • ( / ): запуск / завершение группы.
  • * / + / ?: указание типа повторения.
  • .: сопоставление с любымсимвол.
  • \: исключает символы и запускает объекты.
  • ^: указывает начало соответствующей зоны и отменяет сопоставление в классе символов.
  • $: указывает конец соответствующей зоны.
  • |: указывает на чередование.
  • #: указывает комментарий в свободном интервале.
  • \s: игнорируетсяв свободном интервале.
  • ,: разделяет значения в спецификаторе нумерации.
  • /: запускает или заканчивает выражение.
  • :: выполняет специальные gТипы групп и часть классов символов в стиле Perl.
  • !: Отрицание группы нулевой ширины.
  • < / =: Часть спецификаций группы нулевой ширины.

Примечания:

  • / не является строго обязательным в любой разновидности регулярного выражения.Тем не менее, он защищает в случае, если кто-то (вздрагивает) делает eval("/" + pattern + "/");.
  • , гарантирует, что если строка должна быть целым числом в числовом спецификаторе, она будет правильно вызыватьошибка компиляции RegExp вместо тихой компиляции неправильно.
  • # и \s не нужно экранировать в 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) : '') + ')');
20 голосов
/ 31 октября 2012

В виджете автозаполнения jQueryUI (версия 1.9.1) они используют немного другое регулярное выражение (строка 6753), вот регулярное выражение в сочетании с подходом @bobince.

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
18 голосов
/ 13 мая 2014

Руководство по регулярным выражениям в Mozilla Developer Network предоставляет эту функцию экранирования:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
10 голосов
/ 12 ноября 2016

Ничто не должно мешать вам просто экранировать каждый не алфавитно-цифровой символ:

usersString.replace(/(?=\W)/g, '\\');

Вы теряете определенную степень читабельности при выполнении re.toString(), но вы выигрываете большую простоту (и безопасность).

Согласно ECMA-262, с одной стороны, регулярные выражения "синтаксические символы" всегда не алфавитно-цифровые, так что результат является безопасным, и специальные escape-последовательности (\d, \w, \n) всегда являются буквенно-цифровыми, так что ложные контрольные выходы не будут создаваться.

9 голосов
/ 15 июня 2015

Есть предложение ES7 для RegExp.escape на https://github.com/benjamingr/RexExp.escape/, с полифилом на https://github.com/ljharb/regexp.escape.

5 голосов
/ 04 сентября 2013

Это более короткая версия.

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

Это включает немета-символы %, &, ' и ,, но спецификация JavaScript RegExp позволяет это.

2 голосов
/ 01 августа 2017

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

Для этого примера предположим следующее выражение:

RegExp.escape('be || ! be');

Это белые буквы, цифры и пробелы:

RegExp.escape = function (string) {
    return string.replace(/([^\w\d\s])/gi, '\\$1');
}

Возвраты:

"be \|\| \! be"

Это может не включать символы, которые не нужно экранировать, но это не мешает вашему выражению (может быть, некоторые незначительные штрафы за время - но оно того стоит для безопасности).

2 голосов
/ 05 июля 2017

XRegExp имеет функцию выхода:

XRegExp.escape('Escaped? <.>'); // -> 'Escaped\?\ <\.>'

Подробнее о: http://xregexp.com/api/#escape

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...