Reputation: 5839
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.
x + 2 + 3
but not in 2.5
, 2.52
or 5.2
(because that's the digit 2, not the actual number 2).x + 2.5 + 3
and 2.5
, but not 2.52
or 12.5
.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).
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).
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?
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
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
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