views:

34

answers:

3

Hi

I have an application with a large number of #if debug blocks which kind of look like the the one below:

#if DEBUG
                Console.ForegroundColor = ConsoleColor.DarkCyan;
                Console.WriteLine("oldXml: " + oldXml.OuterXml);
                            Logging.Log("XmlDiff: " + diff_sb.ToString());
                Console.ForegroundColor = ConsoleColor.Cyan;
                            Logging.Log("2XmlDiff: " + diff_sb.ToString());
                Console.WriteLine("newXml: " + newXml.OuterXml);
                Console.ForegroundColor = ConsoleColor.Green;
#endif

I am using Resharper's search pattern matching function and I need to be able to find all instances of the string "Logging.Log" inside of these if debug blocks

Would anyone know what the regex for this pattern search should be?

A: 

How about

#if DEBUG([\s\S]*?)#endif
Confluence
Not a good idea: This will match from the very first `#if DEBUG` to the very last `#endif`.
Tim Pietzcker
@Tim Good catch. Made it lazy instead.
Confluence
A: 

Probably one of the easier ways to do this is in two steps. First, use a regex to collect all the blocks of text between #if DEBUG and #endif. Then go through each one of those blocks and find the string "Logging.Log".

If you want to preserve exact position, you'll have to save the offset for each chunk in the first step and add the offsets in the second step.

JoshD
A: 
(?<=#if DEBUG(?:(?!#endif\b).)*)Logging\.Log[^\r\n]*(?=.*#endif)

will match Logging.Log and whatever else follows on that line only if it's between #if DEBUG and #endif. Note that you need to use RegexOptions.Singleline for this to work. This regex relies on a feature that only few regex engines have, namely infinite repetition inside lookbehind assertions. Fortunately, .NET is among those.

In C#:

StringCollection resultList = new StringCollection();
Regex regexObj = new Regex(@"(?<=#if DEBUG(?:(?!#endif\b).)*)Logging\.Log[^\r\n]*(?=.*#endif)", RegexOptions.Singleline);
Match matchResult = regexObj.Match(subjectString);
while (matchResult.Success) {
    resultList.Add(matchResult.Value);
    matchResult = matchResult.NextMatch();
} 

Explanation:

# from the current position, look behind in the string to check...
(?<=           # whether it is possible to match...
 #if DEBUG     # the literal text # if DEBUG
 (?:           # followed by...
  (?!#endif\b) # (as long as we can't match #endif along the way)
  .            # any character
 )*            # any number of times
)              # end of lookbehind assertion.
Logging\.Log   # Then match Logging.Log,
[^\r\n]*       # followed by any character(s) except newlines.
(?=            # as long as there is (further up ahead)...
 .*#endif      # any number of characters, followed by #endif
)              # end of lookahead

If you're sure that every #if DEBUG ends with an #endif, then you can drop the (?=.*#endif).

Tim Pietzcker