Есть ли функция RegExp.escape в Javascript?

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

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

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

Ответы

Ответ 1

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

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

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

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

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

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

И да, это разочаровывает неудача, что это не часть стандартного JavaScript.

Ответ 2

Для тех, кто использует lodash, с версии v3.0.0, функция _. escapeRegExp встроена:

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

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

Ответ 3

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

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

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: Игнорируется в режиме свободного интервала.
  • ,: разделяет значения в спецификаторе нумерации.
  • /: начинает или завершает выражение.
  • :: Завершает специальные типы групп и часть классов символов в стиле 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) : '') + ')');

Ответ 5

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

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

Ответ 6

Ничто не должно препятствовать простому экранированию каждого не-буквенно-цифрового символа:

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

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

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

Ответ 8

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

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

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

Ответ 9

escapeRegExp = function(str) {
  if (str == null) return '';
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};

Ответ 10

XRegExp имеет функцию escape:

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

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

Ответ 11

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

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

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

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

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

Возврат:

"be \|\| \! be"

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

Ответ 12

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

Если вы избегаете всего регулярного выражения и выполняетесь с ним, цитируя метасимволы, которые являются автономными (., ?, +, *, ^, $, |, \) или начать что-то ((, [, {) - все, что вам нужно:

String.prototype.regexEscape = function regexEscape() {
  return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};

И да, это разочаровывает, что JavaScript не имеет такой функции, как этот встроенный.

Ответ 13

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, '\\$&'));

Ответ 14

Другой (гораздо более безопасный) подход состоит в том, чтобы экранировать все символы (а не только несколько специальных, которые мы знаем в настоящее время), используя escape-формат Unicode \u{code}:

function escapeRegExp(text) {
    return Array.from(text)
           .map(char => '\\u{${char.charCodeAt(0).toString(16)}}')
           .join('');
}

console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'

Обратите внимание, что для работы этого метода необходимо указать флаг u:

var expression = new RegExp(escapeRegExp(usersString), 'u');

Ответ 15

Только когда-либо было и будет 12 метасимволов, которые нужно экранировать
считаться буквальным.

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

Заменить строку, используя этот

var escaped_string = oldstring.replace( /[\\^$.|?*+()[{]/g, '\\$&' );