【问题标题】:replace variable names with string.replace(regex, value) [duplicate]用 string.replace(regex, value) 替换变量名
【发布时间】:2020-05-04 00:00:45
【问题描述】:

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

如果我有一个类似的字符串

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 的参数。

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

【问题讨论】:

  • 你使用什么编程语言?
  • 打字稿或javascript。
  • If I have a string like ...我们确实需要在这里看到几个具体的实际示例。
  • 如果它适用于我提供的示例字符串,它将涵盖几乎所有的基础。例如 /b 不会与 (months*7) 一起工作,我不认为。
  • s.replace(/\bmonths\b/g, 12) 有什么问题?输出为12 + 3 + (startmonths * 3) + 12 - (12*7) + (monthsend*5)

标签: javascript regex ecmascript-2018


【解决方案1】:

这似乎无需后视或前瞻即可工作:

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

【讨论】:

  • 我会查看链接。我实际上正在寻找使用正则表达式来解析用户提供的“公式”的含义,其中有“变量”,如天、月和小时,用户提供像“(小时 * 6)+ 天”这样的变量,以及在别处定义小时和天的值。有点像一个没有函数的非常简单的电子表格公式解析器。
【解决方案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);

【讨论】:

  • 我喜欢\w 的简写形式[A-Za-z0-9_]。但是,后面的加号可能是不必要的。例如,(?&lt;![\w])(months)(?![\w]) 也完成了任务。
【解决方案3】:

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

解释:

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

month = 匹配 month 字面意思

Demo

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

$- 匹配字符串结尾

将其替换为 \112\2 - \1 - 第一个杯子修整组,\2 - 第二个捕获组

【讨论】:

  • my testing(^|[^a-z])month(monthsend*5) 中捕获(month,这是一个误报。
  • my tool 中,将($|[^a-z]) 添加到末尾会导致它与anything 不匹配。不过方法很有趣。
  • @LonnieBest Bacuse 它不应该匹配所以它是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 2021-09-28
  • 2022-01-04
  • 2013-01-04
相关资源
最近更新 更多