我正在尝试在JavaScript中构建一个匹配算术运算部分的正则表达式。例如,以下是一些输入和预期输出:
What is 7 minus 5? >> ['7','minus','5']
What is 6 multiplied by -3? >> ['6','multiplied by', '-3']
我有这个工作正则表达式:/^What is (-?\d+) (minus|plus|multiplied by|divided by) (-?\d+)\?$/
现在我想扩展以捕获其他操作。例如:
What is 7 minus 5 plus 3? >> ['7','minus','5','plus','3']
所以我使用了:^What is (-?\d+)(?: (minus|plus|multiplied by|divided by) (-?\d+))+\?$
。但它产生了:
What is 7 minus 5 plus 3? >> ['7','plus','3']
为什么跳过减去5 ?如何按照我的意愿将其包含在结果中? (here is my sample)
答案 0 :(得分:2)
您面临的问题来自于捕获组只能返回一个值。如果相同的捕获组具有多个值(就像在您的情况下那样),它将始终返回最后一个值。
我喜欢在http://www.rexegg.com/regex-capture.html#spawn_groups
解释它的方式您在模式中看到的捕获括号只捕获一个 组。因此,在
(\d)+
中,捕获组并不会像你一样神奇地变成蘑菇 沿着弦走下去。相反,他们反复提到第1组, 第1组,第1组...如果你在1234上试试这个正则表达式(假设你的正则表达式 味道甚至允许它),第1组将包含4 - 即。最后一次捕获。实质上,每次正则表达式迭代时,第1组都会被覆盖 通过捕捉括号。
所以诀窍是使用带有全局标志(g)的正则表达式并多次执行表达式,当使用g标志时,以下执行从最后一个结束开始。
我制作了一个正则表达式,向您展示策略,隔离公式,然后迭代直到找到所有内容。
var formula = "What is 2 minus 1 minus 1";
var regex = /^What is ((?:-?\d+)(?: (?:minus|plus|multiplied by|divided by) (?:-?\d+))+)$/
if (regex.exec(formula).length > 1) {
var math_string = regex.exec(formula)[1];
console.log(math_string);
var math_regex = /(-?\d+)? (minus|plus|multiplied by|divided by) (-?\d+)/g
var operation;
var result = [];
while (operation = math_regex.exec(math_string)) {
if (operation[1]) {
result.push(operation[1]);
}
result.push(operation[2], operation[3]);
}
console.log(result);
}
另一个解决方案,如果你不需要任何花哨的东西,那就是删除“What is”,将multiplied by
替换为multiplied_by
(对于划分的相同)并将字符串拆分为空格。
var formula = "What is 2 multiplied by 1 divided by 1";
var regex = /^What is ((?:-?\d+)(?: (?:minus|plus|multiplied by|divided by) (?:-?\d+))+)$/
if (regex.exec(formula).length > 1) {
var math_string = regex.exec(formula)[1].replace('multiplied by', 'multiplied_by').replace('divided by', 'divided_by');
console.log(math_string.split(" "));
}
答案 1 :(得分:1)
正则表达式中的每个捕获组只能包含一个值。所以,如果你对某个组有重复,那么你只会为该组获得一个结果(通常是最后一个,我认为)。在你的情况下,它是以下:
(?: (minus|plus|multiplied by|divided by) (-?\d+))+
您正在重复非捕获组,将重复匹配。但是最终内部的群体只能进行一次匹配,这是最后一次重复的结果。
您应该切换到匹配的令牌,而不是让单个正则表达式试图匹配整个短语并通过捕获组解析它。类似于两个步骤的过程,您首先验证整个短语是否正确构建(以“什么是«,以......?«结尾”等),然后是一个提取单个标记的过程,例如:
之类的东西-?\d+|minus|plus|multiplied by|divided by