将变量名替换为 string.replace(regex, value)。

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_]), 但它捕获了'months'前面和后面的字符,所以我不能将其作为string.replace的参数。
是否有解决方法,或者我必须忘记replace函数并手动使用find和splice等功能呢?

你使用的编程语言是什么? - Tim Biegeleisen
typescript或javascript - GGizmos
如果我有一个字符串,就像...我们真的需要看到几个具体的实际例子。 - Tim Biegeleisen
糟糕,不好意思,打错字了。 - GGizmos
2
s.replace(/\bmonths\b/g, 12)有什么问题?输出是12 + 3 + (startmonths * 3) + 12 - (12*7) + (monthsend*5) - Nick
显示剩余2条评论
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的屏幕截图: enter image description here

你是对的,回顾先行断言并不是在所有浏览器中都能工作。然而,在Chrome中,它们可以工作,并且很快也将可以在Firefox中使用。回顾先行断言被添加到2018规范中,因此在2020年这里它们还没有普及是可耻的。

在支持回顾先行断言的情况下,我会像这样同时使用"负回顾先行"和"负前瞻":

(?<![A-Za-z0-9_])(months)(?![A-Za-z0-9_])

上述的速记方法是:
(?<![\w])(months)(?![\w])

来自regexr.com的截图: 在这里输入图片描述


我会查看这个链接。实际上,我想使用正则表达式来解析用户提供的“公式”的含义,其中包括像天、月和小时这样的“变量”,用户提供了一个类似于“(hours*6) + days”的值,并在其他地方定义了小时和天的值。有点像一个非常简单的电子表格公式解析器,没有函数。 - GGizmos

0

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

解释:

(^ | [^a-z]) - 匹配字符串的开头 ^ 或(由于交替 |)除字母以外的任何内容,最后将其存储在第一个捕获组中。

month = 匹配月份文字。

演示

编辑:小修正:(^|[^a-z])month($|[^a-z])

$- 匹配字符串的结尾。

\1\2替换它- \1 - 第一个捕获组,\2- 第二个捕获组。


我的测试中,(^|[^a-z])month捕获了(monthsend*5)中的(month,这是一个误报。 - Lonnie Best
我的工具中,添加($|[^a-z])到结尾会导致它不匹配任何东西。虽然这是一种有趣的方法。 - Lonnie Best
@LonnieBest 因为它不应该匹配,所以它是正确的。 - Michał Turczyn

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);

1
我喜欢\w这个简写表示[A-Za-z0-9_]。然而,后面的加号可能是不必要的。例如,(?<![\w])(months)(?![\w])也可以完成任务。 - Lonnie Best

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接