заменить имена переменных на string.replace(регулярное выражение, значение)
Попытка сделать то, что я считал довольно простой заменой строки, оказалась более сложной, чем я думал.
Если у меня есть строка вроде
months + 3 + (startmonths * 3) + months - (months*7) + (monthsend*5)
Для ясности, "формула", которую я анализирую, предоставляется пользователем и может состоять из любых серий имен переменных, операторов (+*/-) и скобок, которые пользователь может придумать. Что мне нужно сделать, так это сначала заменить переменные числами, а затем оценить полученное выражение.,
я ищу, как заменить все вхождения слов месяцев, скажем, "12" с помощью функции string.replace.
Так что, надеюсь, результат функции будет
12 + 3 + (startmonths * 3) + 12 - (12*3) + (monthsend*5)"
Похоже, мне нужно регулярное выражение, чтобы избежать замены в строках, таких как "startmonths", возможно, у меня сложилось впечатление, что на самом деле это невозможно сделать в регулярном выражении javascript, потому что "lookbehind" редко поддерживаются в современных браузерах.
Я пробовал использовать
[^A-Za-z9-9_](months)(?:[^A-Za-z0-9_])
но это захватывает символ до и после месяца, поэтому я не могу использовать его в качестве параметра для string.replace.
Есть ли какое-то обходное решение, или мне нужно забыть о функции замены и сделать это "вручную" с помощью поиска, соединения и т. Д.?
3 ответа
Кажется, это работает без необходимости смотреть назад или вперед:
let regExMonth = /\bmonths\b/gm;
let str = "months + 3 + (startmonths * 3) + months - (months*7) + (monthsend*5)";
str = str.replace(regExMonth, "12");
console.log(str);
Скриншот с сайта regexr.com:
Вы правы, что ретроспективы работают не везде. Однако они работают в Chrome и скоро будут работать в Firefox. В спецификации 2018 года были добавлены ретроспективы, поэтому жаль, что они еще не стали повсеместными в 2020 году.
Там, где поддерживается просмотр назад, я бы использовал как "отрицательный взгляд назад", так и "отрицательный взгляд вперед", например:
(?<![A-Za-z0-9_])(months)(?![A-Za-z0-9_])
Сокращение приведенного выше будет:
(?<![\w])(months)(?![\w])
Скриншот с сайта regexr.com:
Я могу предложить (^|[^a-z])month
Пояснение:
(^|[^a-z])
- сопоставить начало строки ^
или (из-за чередования |
) antyhing, кроме букв, из-за отрицательного класса символов [^a-z]
и, наконец, сохраните его в первой группе захвата.
month
= совпадение month
буквально
РЕДАКТИРОВАТЬ: небольшая поправка: (^|[^az]) месяц ($|[^az])
$
- сопоставить конец строки
Замени его на \112\2
- \1
- первая группа, \2
- вторая группа захвата
Вы можете использовать отрицательный взгляд вперед и назад одновременно
const regex = /(?<![\w+])(months)(?![\w+])/gm;
const str = `months + 3 + (startmonths * 3) + months - (months*7) + (monthsend*5)`;
const subst = `12`;
const result = str.replace(regex, subst);
console.log('Substitution result: ', result);