3

尝试做我认为是相当简单的字符串替换,但结果比我想象的要复杂。

如果我有一个字符串

months + 3 + (startmonths * 3) + months - (months*7) + (monthsend*5)

为清楚起见,我正在解析的“公式”是用户提供的,并且可以包含用户可以提出的任何一系列变量名称和运算符 (+*/-) 和括号。我需要做的是首先用数字替换变量,然后评估结果表达式。,

我正在寻找的是如何使用 string.replace 函数替换所有出现的单词months,比如“12”。

所以希望函数的输出是

 12 + 3 + (startmonths * 3) + 12 - (12*3) + (monthsend*5)"

似乎我需要一个正则表达式来避免替换像“startmonths”这样的字符串,我可能认为它实际上不可能在 javascript 正则表达式中执行,因为现代浏览器很少支持“lookbehinds”。

我尝试使用 [^A-Za-z9-9_](months)(?:[^A-Za-z0-9_]) ,但它捕获了“月”之前和之后的字符,所以我不能将它用作 string.replace 的参数。

是否有一些解决方法,或者我是否必须忘记替换功能并使用查找和拼接等“手动”完成?

4

3 回答 3

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的屏幕截图: 在此处输入图像描述

于 2020-01-17T05:38:29.683 回答
0

您可以同时使用负前瞻和后视

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);
于 2020-01-17T06:16:44.930 回答
0

我可以建议(^|[^a-z])month

解释:

(^|[^a-z])- 匹配字符串的开头^或(由于交替|)由于否定字符类而导致的字母除外[^a-z],最后将其存储在第一个捕获组中。

monthmonth=字面上匹配

演示

编辑:小更正: (^|[^az])month($|[^az])

$- 匹配字符串结尾

将其替换为\112\2- \1- first cuptruing group, \2- second capture group

于 2020-01-17T07:30:45.533 回答