Haseeb Khan Haseeb Khan - 2 months ago 11
C# Question

C# Regex get specific character with decimal number

I need a regex which return specific character with a decimal number up to 1 place

I have string text

(AvgC20.1 > 980000) && (C1>C2) MaxC20 MinC20.14


after applying regex get the following result

AvgC20, MaxC20, MinC20


This is the regex I am using

(Avg|Max|Min)[OHLVC]\d+


which return what I want but not return the decimal number up to one place

but I need result like this

AvgC20.1, MaxC20, MinC20.1

Answer

Add an optional (?:\.\d+)? matching 1 or 0 occurrences of a . followed with 1 or more digits:

(?:Avg|Max|Min)[OHLVC]\d+(?:\.\d+)?
                         ^^^^^^^^^^

See the regex demo

enter image description here

The (?:...)? is an optional non-capturing group. It is optional (=matches one or zero occurrences) due to the ? quantifier (a greedy one, that is why I mention one or zero, not zero or one). The non-capturing group is used for grouping purposes, without creating a buffer for the captured value in the memory. I suggested using the non-capturing group because the final result should be equal to the whole match value, so, no need tracking and storing those subvalues.

NOTE on the non/capturing groups in .NET: In .NET code, you can actually use numbered capturing groups and make them non-capturing by using the RegexOptions.ExplicitCapture flag. Then, memory buffers will get created only for named capturing groups (like (?<gr1>...)).

Pattern details:

  • (?:Avg|Max|Min) - Either Avg, Max or Min
  • [OHLVC] - one uppercase letter from the set
  • \d+ - 1 or more digits
  • (?:\.\d+)? - an optional sequence of a . followed with 1 or more digits.

Sidenote: it is best practice to disallow branches of the same alternation group to match at one and the same location, and (?:Avg|Max|Min) is better written as (?:Avg|M(?:ax|in)). However, what is good for the machine is not that fine for a human eye, so due to readability reasons, I'd advise to keep the first group as is.

C# demo (note that the RegexOptions.ExplicitCapture is passed with the help of the inline (?n) option):

var s = "(AvgC20.1 > 980000) && (C1>C2) MaxC20 MinC20.14";
var pattern = @"(?n)(Avg|Max|Min)[OHLVC]\d+(\.\d+)?";
var result = Regex.Matches(s, pattern)
        .Cast<Match>()
        .Select(p => p.Value)
        .ToList();
foreach (var r in result) // Demo printing the results
    Console.WriteLine(r);
Comments