无法制作动态增长的正则表达式

时间:2017-10-04 13:07:47

标签: javascript regex

我正在尝试在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

2 个答案:

答案 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