Почему это регулярное выражение не работает, если я использую переменную вместо прямого использования соответствующей строки? - PullRequest
0 голосов
/ 01 февраля 2019

Это мой код:

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

function replace(str, needle, replacement) {
  var expr = '([^\\[]*)(' +
      escape(needle) + ')([^\\]]*)';
  return str.replace(new RegExp(expr, 'g'), '$1' + replacement + '$3');
}

document.body.innerHTML += replace('hello() [hello()] test()', '()', '@');

Проблема в следующей строке:

var expr = '([^\\[]*)(' +
  escape(needle) + ')([^\\]]*)';

Если я заменю ее на

var expr = '([^\\[]*)(' +
  '\\(\\)' + ')([^\\]]*)';

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

alert(escape('()'));

В чем моя ошибка?

Не работает скрипка: https://jsfiddle.net/rmof8pzv/
Рабочая скрипка: https://jsfiddle.net/gpoy2rbt/

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Кажется, вы смешиваете экранирование обратной косой черты.

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

console.log('\\');

В регулярном выражении вам также нужно экранировать символы с одним обратным слешем, но если вы делаете это в строковом литерале, вам нужно дважды экранировать их по вышеуказанной причине.Вот почему ваш рабочий пример работает.Но в вашей функции escape() вы добавляете две обратных косых черты вместо одной.Просто измените '\\\\$&' на '\\$&', и оно должно работать нормально.

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

function replace(str, needle, replacement) {
  var expr = '([^\\[]*)(' +
      escape(needle) + ')([^\\]]*)';
  return str.replace(new RegExp(expr, 'g'), '$1' + replacement + '$3');
}

console.log(replace('hello() [hello()] test()', '()', '@'));
0 голосов
/ 01 февраля 2019

Проблема возникает из-за того, что двойная обратная косая черта экранирована внутри функции escape '\\\\$&', вам не нужно избегать этого, потому что ее нужно экранировать только один раз, как '\\$&'.Таким образом, изменение функции escape дало мне ожидаемый результат.

function escape(str) {
  return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...