回到课程

解析算数表达式

一条算数表达式包括两个数字及其中间的一个运算符。例如:

  • 1 + 2
  • 1.2 * 3.4
  • -3 / -6
  • -2 - 2

运算符可能为:"+""-""*""/"

开头、结尾和中间可能存在额外的空格。

编写一个函数 parse(expr)。它接收一个表达式作为参数,并且返回一个包含以下三个值的数组:

  1. 第一个数。
  2. 运算符。
  3. 第二个数。

例如:

let [a, op, b] = parse("1.2 * 3.4");

alert(a); // 1.2
alert(op); // *
alert(b); // 3.4

回顾之前的问题,我们用 -?\d+(\.\d+)? 来匹配数字。

[-+*/] 匹配运算符。我们把 - 放在最前面,因为如果放在中间的话,则表示字符范围,这并不是我们想要的。

注意,在 JavaScript 中,/.../ 中的 / 需要被转义。

我们需要匹配一个数字、一个运算符,还有另一个数字。除此以外,还有它们之间可能存在的空格。

完整的正则表达式为:-?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?

为了将得到的结果转化为数组,我们须将所需的数据:数字及运算符,包裹在括号中,对应的表达式为:(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)

实际操作:

let reg = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;

alert( "1.2 + 12".match(reg) );

结果包括:

  • result[0] == "1.2 + 12"(完整匹配)
  • result[1] == "1"(第一个捕获组)
  • result[2] == ".2"(第二个捕获组 —— 小数部分)
  • result[3] == "+"(…)
  • result[4] == "12"(…)
  • result[5] == undefined(最后一个小数部分不存在,因此为 undefined)

我们只需要数字和运算符,不需要小数部分。

因此,我们可以加上 ?: 来去除多余的捕获组,例如:(?:\.\d+)?

最终答案:

function parse(expr) {
  let reg = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/;

  let result = expr.match(reg);

  if (!result) return;
  result.shift();

  return result;
}

alert( parse("-1.23 * 3.45") );  // -1.23, *, 3.45