Tim
Tim

Reputation: 5839

C# regex to match exact number (including integers and decimals)

Summary

I'm trying to use regex to match an exact number (i.e. the number as a human would understand it, not the digit itself) within a larger string. The number I'm trying to match will vary. It could be an integer or a decimal, and it could be a single digit or multiple digits.

Examples

Note that 2 and 2.5 are just examples, I want this to work for any arbitrary positive number (if it works for negative numbers that's not a problem, but it's also not a requirement).

Initial attempt

I started with (\bX\b)+ (where X will be the number I want to match), which works when X is 2.5 but not when X is 2. This is because it's using word breaks to identify the start and end of the number, but a decimal point counts as a word break. This means that if X is 2 (i.e. the regex is (\b2\b)+) it will match the number 2 (correct), but also 2.x (incorrect) and x.2 (also incorrect).

Current attempt

I've fixed the problem of 2.x by changing the expression to (\bX\b(?!\.))+. This excludes numbers where X is followed by a decimal point, so if X is 2 it will match 2 (correct), will not match 2.x (correct) but will still match x.2 (incorrect). If X is a decimal number, this works correctly (so if X is 2.5 it will correctly match 2.5 and exclude 12.5 or 2.51).

How can I avoid matching X when it's preceded by a decimal point?

Real use-case

If it helps, the end goal is to use this with the C# Regex.Replace function as follows:

private static string ReplaceNumberWithinFormula(string originalFormula, double numberToReplace, string textToReplaceNumberWith)
{
    return Regex.Replace(originalFormula, $@"(\b{numberToReplace}\b(?!\.))+", textToReplaceNumberWith);
}

Upvotes: 1

Views: 1143

Answers (3)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626699

You may use

private static string ReplaceNumberWithinFormula(string originalFormula, double numberToReplace, string textToReplaceNumberWith)
{
    return Regex.Replace(originalFormula, $@"(?<!\d\.?){Regex.Escape(numberToReplace.ToString())}(?!\.?\d)", textToReplaceNumberWith);
}

See the C# demo

The (?<!\d\.?){Regex.Escape(numberToReplace.ToString())}(?!\.?\d), given the variable inside is equal to 2.5, translates into (?<!\d\.?)2\.5(?!\.?\d) and matches 2.5 only if

  • (?<!\d\.?) - not preceded with a digit and an optional .
  • (?!\.?\d) - not followed with an optional . and then a digit.

See the regex demo.

A simpler regex that will work with the input like you have only can be a word boundary + lookarounds based pattern like

private static string ReplaceNumberWithinFormula(string originalFormula, double numberToReplace, string textToReplaceNumberWith)
{
    return Regex.Replace(originalFormula, $@"\b(?<!\.){Regex.Escape(numberToReplace.ToString())}\b(?!\.)", textToReplaceNumberWith);
}

Here, the regex will look like \b(?<!\.)2\.5\b(?!\.) and will match a word boundary position first (with \b), then will make sure there is no . right before the location (with (?<!\.)), then will match 2.5, assure there is no word char (letter, digit, or _) right after the number and then will check that there is no . after the number. See this regex demo.

It is equal to $@"(?<![\w.]){Regex.Escape(numberToReplace.ToString())}(?![\w.])", and is more restrictive than the top solution that will let you match the exact float or integer number in any context.

Upvotes: 2

Saksham
Saksham

Reputation: 9380

I think this is what you are looking for

^\d+(\.\d+)?\b
  • This matches whole numbers like 2

  • Matches decimal numbers like 2.1

  • Does not match patterns like 2. or .3

Upvotes: -1

ALFA
ALFA

Reputation: 1744

Add also a negative lookbehind:

((?<!\.)\b2\b(?!\.))+

Check the demo.

Upvotes: 0

Related Questions