【问题标题】:Pattern for formula which contains number, letters ,expressions and brackets包含数字、字母、表达式和括号的公式模式
【发布时间】:2019-11-10 07:47:35
【问题描述】:

我正在尝试为以下示例的公式编写正则表达式。

  1. C=A+B => Output for match will be {A, +, B}
  2. D= C+50 => Output for match will be{C, +, 50}
  3. E = (A+B)*C -100 => Output for match will be{(, A, +, B, ), *, C, -, 100}

我尝试了正则表达式

[A-Z(\d*)*+/-]

这个的输出是{A, +, 5, 0}

但它没有为A+50 提供正确的输出

【问题讨论】:

  • 正则表达式是分析表达式的一个糟糕的选择。还有其他几种更好的工具和技术。您可以先阅读问题上parsing 标签上的信息。

标签: c# regex parsing


【解决方案1】:

我建议FSM(有限状态机)而不是正则表达式。我们这里有3 状态:

  1. 既不是变量,也不是数字0
  2. 在变量1
  3. 号码内2

代码:

private static IEnumerable<string> Parse(string formula) {
  int state = 0;

  StringBuilder buffer = new StringBuilder();

  foreach (var c in formula) {
    if (state == 0) { // neither var nor number
      if (char.IsWhiteSpace(c))
        continue;

      if (char.IsDigit(c)) {
        buffer.Append(c);
        state = 2;
      }
      else if (char.IsLetter(c)) {
        buffer.Append(c);
        state = 1;
      } 
      else 
        yield return c.ToString();
    }
    else if (state == 1) { // within variable
      if (char.IsDigit(c) || char.IsLetter(c))
        buffer.Append(c);
      else {
        yield return buffer.ToString();
        buffer.Clear(); 

        state = 0;

        if (!char.IsWhiteSpace(c))
          yield return c.ToString();
      }
    }
    else if (state == 2) { // within number
      if (char.IsDigit(c))
        buffer.Append(c);
      else if (char.IsLetter(c)) {
        // 123abc we turn into 123 * abc
        yield return buffer.ToString();
        buffer.Clear();

        state = 1; 

        yield return "*";

        buffer.Append(c);
      }
      else {
        yield return buffer.ToString();
        buffer.Clear();

        state = 0;

        if (!char.IsWhiteSpace(c))
          yield return c.ToString();
      } 
    }
  } 

  if (buffer.Length > 0)
    yield return buffer.ToString();
}

演示:

  string[] tests = new string[] {
    "C=A+B",
    "D= C+50",
    "E = (A+B)*C -100",
  };

  string result = string.Join(Environment.NewLine, tests
    .Select(test => new {
      formula = test,
      parsed = Parse(test)
        .SkipWhile(term => term != "=") // we don't want "C = " or alike part
        .Skip(1)
    })
    .Select(test => $"{test.formula,-20} => {string.Join(", ", test.parsed)}"));

 Console.Write(result);

结果:

C=A+B                => A, +, B
D= C+50              => C, +, 50
E = (A+B)*C -100     => (, A, +, B, ), *, C, -, 100

【讨论】:

    【解决方案2】:

    |(或)用于单个项目,例如模式

    \d+|\W|\w

    翻译成任何数字或任何非字母字符或任何字母字符。

    【讨论】:

      猜你喜欢
      • 2020-07-02
      • 2016-12-19
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多