Jobert Enamno
Jobert Enamno

Reputation: 4461

Regex Find All Search Keyword Matches

I have string

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

and I have regex

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

from that string I want to search from my regex all ROUND functions like below:

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

From MatchCollection result I got only one match. I'm expecting two matches since my string has two ROUND functions. Is there missing on my regex? Please help. I'm not good in regex.

Updated:

Here's the screenshot from online regex. As you can see only the first ROUND function has been matched. I need to get the second ROUND function too.

http://regexhero.net/tester/ http://regexhero.net/tester/

Updated:

To be clearer what output for the following regex I'm expecting.

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

Currently it matches only for the following strings:

  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)

I want that regex to match also the following

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

Please help.

Upvotes: 0

Views: 111

Answers (1)

Paul
Paul

Reputation: 1069

I would recommend a tool like gplex/gppg, GOLD, ANTLR to do this kind of work, especially since you will be evaluating the parsed result.

If you insist on using .NET RegEx, I suggest you have a look at using Balancing Group Definitions.

If you want something a little easier to deal with, then I would consider writing a simple Recursive Descent Parser to break your input down into a syntax tree, then evaluate it. Wikipedia has a decent sample written in C (without pointers so it is easy to convert to .net) which I have copied below as well.

Balancing Group Sample

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>

Recursive Descent Parser Sample (from 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);
}

Upvotes: 2

Related Questions