Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You didn't show us how you're applying the regex, so here's a demo I whipped up:</p> <pre><code>private static void ParseIt(string subject) { Console.WriteLine("subject : {0}\n", subject); Regex openers = new Regex(@"[[{(]"); Regex closers = new Regex(@"[]})]"); Regex ops = new Regex(@"[*+/-]"); Regex VariableOrConstant = new Regex(@"((\d+(\.\d+)?)|\w+)" + ops + "?"); Regex splitter = new Regex( openers + @"(?&lt;FIRST&gt;" + VariableOrConstant + @")+" + closers + ops + @"?" + @"|" + @"(?&lt;SECOND&gt;" + VariableOrConstant + @")" + ops + @"?", RegexOptions.ExplicitCapture ); foreach (Match m in splitter.Matches(subject)) { foreach (string s in splitter.GetGroupNames()) { Console.WriteLine("group {0,-8}: {1}", s, m.Groups[s]); } Console.WriteLine(); } } </code></pre> <p>output:</p> <pre><code>subject : 4/(2*X*[2+1]) group 0 : 4/ group FIRST : group SECOND : 4/ group 0 : 2* group FIRST : group SECOND : 2* group 0 : X* group FIRST : group SECOND : X* group 0 : [2+1] group FIRST : 1 group SECOND : </code></pre> <p>As you can see, the term <code>[2+1]</code> <strong>is</strong> matched by the first part of the regex, as you intended. It can't do anything with the <code>(</code>, though, because the next bracketing character after that is another "opener" (<code>[</code>), and it's looking for a "closer".</p> <p>You <em>could</em> use .NET's "balanced matching" feature to allow for grouped terms enclosed in other groups, but it's not worth the effort. Regexes are not designed for parsing--in fact, parsing and regex matching are fundamentally different kinds of operation. And this is a good example of the difference: a regex actively seeks out matches, skipping over anything it can't use (like the open-parenthesis in your example), but a parser has to examine every character (even if it's just to decide to ignore it).</p> <p>About the demo: I tried to make the minimum <em>functional</em> changes necessary to get your code to work (which is why I didn't correct the error of putting the <code>+</code> <em>outside</em> the capturing group), but I also made several <em>surface</em> changes, and those represent active recommendations. To wit:</p> <ul> <li>Always use verbatim string literals (<code>@"..."</code>) when creating regexes in C# (I think the reason is obvious).</li> <li>If you're using capturing groups, use named groups whenever possible, but don't use named groups and numbered groups in the same regex. Named groups save you the hassle of keeping track of what's captured where, and the <code>ExplicitCapture</code> option saves you having to clutter up the regex with <code>(?:...)</code> wherever you need a non-capturing group.</li> </ul> <p>Finally, that whole scheme of building a large regex from a bunch of smaller regexes has very limited usefulness IMO. It's very difficult to keep track of the interactions between the parts, like which part's inside which group. Another advantage of C#'s verbatim strings is that they're multiline, so you can take advantage of free-spacing mode (a.k.a. <code>/x</code> or COMMENTS mode):</p> <pre><code> Regex r = new Regex(@" (?&lt;GROUPED&gt; [[{(] # opening bracket ( # group containing: ((\d+(\.\d+)?)|\w+) # number or variable [*+/-]? # and proceeding operator )+ # ...one or more times []})] # closing bracket [*+/-]? # and proceeding operator ) | (?&lt;UNGROUPED&gt; ((\d+(\.\d+)?)|\w+) # number or variable [*+/-]? # and proceeding operator ) ", RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace ); </code></pre> <p>This is not intended as a solution to your problem; as I said, that's not a job for regexes. This is just a demonstration of some useful regex techniques.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload