【问题标题】:Regex Find All Search Keyword Matches正则表达式查找所有搜索关键字匹配
【发布时间】:2015-03-03 20:26:07
【问题描述】:

我有字符串

var statement="ROUND(CDBL('0'),2)=ROUND((CDBL('0.00')*CDBL('0')/100),2)"

我有正则表达式

@"[ROUND^]+\(\w+\([\'^].*?[\']\)+[\,]+[\d]+\)|[ROUND^]+\(+[\']+.+[\']+[\,]+[\d]+\)"

我想从我的正则表达式中搜索所有 ROUND 函数,如下所示:

 MatchCollection roundFunctions = Regex.Matches(statement, @"[ROUND^]+\(\w+\([\'^].*?[\']\)+[\,]+[\d]+\)|[ROUND^]+\(+[\']+.+[\']+[\,]+[\d]+\)");

从 MatchCollection 结果中,我只得到了一场比赛。我期待两个匹配,因为我的字符串有两个 ROUND 函数。我的正则表达式是否缺少?请帮忙。我不擅长正则表达式。

更新:

这是来自在线正则表达式的屏幕截图。如您所见,只有第一个 ROUND 函数已匹配。我也需要获得第二个 ROUND 功能。

http://regexhero.net/tester/

更新:

为了更清楚我期望的以下正则表达式的输出。

[ROUND^]+\(\w+\([\'^].*?[\']\)+[\,]+[\d]+\)|[ROUND^]+\(+[\']+.+[\']+[\,]+[\d]+\)

目前仅匹配以下字符串:

  1. ROUND(CDBL('0'),2)
  2. ROUND(CDBL('1'),2)+ROUND(CDBL('3'),2)
  3. ROUND(CDBL('4.25'),3)*ROUND(CDBL('5.76'),4)
  4. ROUND(CDBL('20.3'),2)/ROUND(CDBL('10'),2)
  5. ROUND(CDBL('100.55'),2)-ROUND(CDBL('10.2'),2)

我希望该正则表达式也匹配以下内容

  1. ROUND((CDBL('5.24.00')*CDBL('7.4')/100),2)
  2. ROUND((CDBL('300.45.00')-CDBL('100.4')/100),2)

请帮忙。

【问题讨论】:

  • 你需要 ROUND 的参数吗?还是仅仅计算 ROUND 调用的次数?
  • @Paul 我需要 round 的参数,因为在匹配之后,我会循环来自 roundFunctions 的 ROUND 匹配来计算每个方程。
  • 你能像 ROUND(ROUND(...)) 这样链接 ROUND 语句吗?如果是这样,我建议您查看语法解析器而不是简单的正则表达式。例如goldparser.org - 他们有用于构建语法和.NET 实现的工具来解析它。
  • [ROUND^]+ 匹配 RO 或 ... 或 ^ 的一个或多个字符。

标签: regex c#-4.0


【解决方案1】:

我会推荐像gplex/gppgGOLD、ANTLR 这样的工具来完成这种工作,尤其是因为您将评估解析的结果。

如果你坚持使用.NET RegEx,我建议你看看使用Balancing Group Definitions

如果您想要一些更容易处理的东西,那么我会考虑编写一个简单的Recursive Descent Parser 将您的输入分解为语法树,然后对其进行评估。 Wikipedia 有一个用 C 编写的不错的示例(没有指针,因此很容易转换为 .net),我也在下面复制了它。

平衡组示例

using System;
using System.Text.RegularExpressions;

class Example
{
   public static void Main() 
   {
      string pattern = "^[^<>]*" +
                       "(" + 
                       "((?'Open'<)[^<>]*)+" +
                       "((?'Close-Open'>)[^<>]*)+" +
                       ")*" +
                       "(?(Open)(?!))$";
      string input = "<abc><mno<xyz>>";

      Match m = Regex.Match(input, pattern);
      if (m.Success == true)
      {
         Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
         int grpCtr = 0;
         foreach (Group grp in m.Groups)
         {
            Console.WriteLine("   Group {0}: {1}", grpCtr, grp.Value);
            grpCtr++;
            int capCtr = 0;
            foreach (Capture cap in grp.Captures)
            {            
                Console.WriteLine("      Capture {0}: {1}", capCtr, cap.Value);
                capCtr++;
            }
          }
      }
      else
      {
         Console.WriteLine("Match failed.");
      }   
    }
}
// The example displays the following output: 
//    Input: "<abc><mno<xyz>>" 
//    Match: "<abc><mno<xyz>>" 
//       Group 0: <abc><mno<xyz>> 
//          Capture 0: <abc><mno<xyz>> 
//       Group 1: <mno<xyz>> 
//          Capture 0: <abc> 
//          Capture 1: <mno<xyz>> 
//       Group 2: <xyz 
//          Capture 0: <abc 
//          Capture 1: <mno 
//          Capture 2: <xyz 
//       Group 3: > 
//          Capture 0: > 
//          Capture 1: > 
//          Capture 2: > 
//       Group 4: 
//       Group 5: mno<xyz> 
//          Capture 0: abc 
//          Capture 1: xyz 
//          Capture 2: mno<xyz>

递归下降解析器示例(来自Wikipedia

typedef enum {ident, number, lparen, rparen, times, slash, plus,
    minus, eql, neq, lss, leq, gtr, geq, callsym, beginsym, semicolon,
    endsym, ifsym, whilesym, becomes, thensym, dosym, constsym, comma,
    varsym, procsym, period, oddsym} Symbol;

Symbol sym;
void getsym(void);
void error(const char msg[]);
void expression(void);

int accept(Symbol s) {
    if (sym == s) {
        getsym();
        return 1;
    }
    return 0;
}

int expect(Symbol s) {
    if (accept(s))
        return 1;
    error("expect: unexpected symbol");
    return 0;
}

void factor(void) {
    if (accept(ident)) {
        ;
    } else if (accept(number)) {
        ;
    } else if (accept(lparen)) {
        expression();
        expect(rparen);
    } else {
        error("factor: syntax error");
        getsym();
    }
}

void term(void) {
    factor();
    while (sym == times || sym == slash) {
        getsym();
        factor();
    }
}

void expression(void) {
    if (sym == plus || sym == minus)
        getsym();
    term();
    while (sym == plus || sym == minus) {
        getsym();
        term();
    }
}

void condition(void) {
    if (accept(oddsym)) {
        expression();
    } else {
        expression();
        if (sym == eql || sym == neq || sym == lss || sym == leq || sym == gtr || sym == geq) {
            getsym();
            expression();
        } else {
            error("condition: invalid operator");
            getsym();
        }
    }
}

void statement(void) {
    if (accept(ident)) {
        expect(becomes);
        expression();
    } else if (accept(callsym)) {
        expect(ident);
    } else if (accept(beginsym)) {
        do {
            statement();
        } while (accept(semicolon));
        expect(endsym);
    } else if (accept(ifsym)) {
        condition();
        expect(thensym);
        statement();
    } else if (accept(whilesym)) {
        condition();
        expect(dosym);
        statement();
    } else {
        error("statement: syntax error");
        getsym();
    }
}

void block(void) {
    if (accept(constsym)) {
        do {
            expect(ident);
            expect(eql);
            expect(number);
        } while (accept(comma));
        expect(semicolon);
    }
    if (accept(varsym)) {
        do {
            expect(ident);
        } while (accept(comma));
        expect(semicolon);
    }
    while (accept(procsym)) {
        expect(ident);
        expect(semicolon);
        block();
        expect(semicolon);
    }
    statement();
}

void program(void) {
    getsym();
    block();
    expect(period);
}

【讨论】:

    猜你喜欢
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    相关资源
    最近更新 更多