Reputation: 642
I apologize if this post is repetitive but I've searched extensively and can't seem to find a solution that works.
I am working on a regular expression for C#. Here are the criteria to match:
A couple of examples:
1,024.12
500.00
10,456.23
2.89
(8,456.15)
(1.63)
This is the current pattern I am using:
^\(?\d+\,?\d+[.]{1}\d{2}\)?
I think this pattern would do the trick, however, there is a string built out of numbers and periods on the same line that matches this pattern. Example:
123.1234.12345.123456789.12345.123
I know this is pretty basic stuff but I'm having trouble getting it to only match the currency portion and not the string above.
Thanks for any suggestions you can provide
Upvotes: 1
Views: 5131
Reputation: 50225
If the goal is just to parse a decimal, decimal.Parse or decimal.TryParse with a properly set NumberStyles will do what you need.
const NumberStyles numberStyles = NumberStyles.AllowParentheses
| NumberStyles.AllowThousands
| NumberStyles.AllowDecimalPoint;
decimal parsed;
var successful = decimal.TryParse(s, numberStyles, CultureInfo.CurrentCulture, out parsed);
Complete test:
var values = new[]
{
"1,024.12",
"500.00",
"10,456.23",
"2.89",
"(8,456.15)",
"(1.63)",
"123.1234.12345.123456789.12345.123"
};
const NumberStyles numberStyles = NumberStyles.AllowParentheses
| NumberStyles.AllowThousands
| NumberStyles.AllowDecimalPoint;
var culture = CultureInfo.CurrentCulture;
foreach (var s in values)
{
decimal parsed;
var successful = decimal.TryParse(s, numberStyles, culture, out parsed);
Console.WriteLine("Successful? {0}; Parsed = {1}",
successful,
successful ? parsed.ToString() : "?");
}
Output:
Successful? True; Parsed = 1024.12 Successful? True; Parsed = 500.00 Successful? True; Parsed = 10456.23 Successful? True; Parsed = 2.89 Successful? True; Parsed = -8456.15 Successful? True; Parsed = -1.63 Successful? False; Parsed = ?
Upvotes: 1
Reputation: 19076
I think this would be a good solution for you:
^\(?(0|[1-9][0-9]{0,2}(?:(,[0-9]{3})*|[0-9]*))\.[0-9]{2}\)?$
This will prevent numbers that don't make much sense such as 004,2.42
Upvotes: 1
Reputation: 9
You should try
^\(?\d+\,?\d+[.]{1}\d{2}\)?\\>
or
^\(?\d+\,?\d+[.]{1}\d{2}\)?\b
so that it doesn't match on partial hits.
Upvotes: 0
Reputation: 19423
Your current expression won't match the fourth 2.89
and the sixth example (1.63)
in your list.
Instead you can use the following expression:
^(\()?[0-9]+(?>,[0-9]{3})*(?>\.[0-9]{2})?(?(1)\))$
This expression matches start-of-line ^
, then it tries to match an optional parentheses (
for negative numbers, the parentheses is captured in a group for a reason that will be cleared soon.
Now it tries to match one or more numbers [0-9]+
, this should cover all whole numbers like 234
, 5652
, etc ..
Then it looks for a possible comma (thousands separator) ,
followed by 3 digits (?>,[0-9]{3})*
repeated zero or more times, this covers numbers that contain thousand separators.
Then it tries to find a decimal point .
followed by exactly 2 digits (?>\.[0-9]{2})?
which is of course optional and this covers decimal numbers.
After that, the expression uses (?(1)\))
- the conditional construct (?(id/name)yes-pattern|no-pattern)
- so that if we actually matched an open parentheses then we should match a closing one, this prevents the expression from matching incorrect negative numbers such as (2.4
with no closing parentheses.
Finally comes the end-of the-string $
to prevent partial matches such as your last example.
Upvotes: 5
Reputation: 43499
\(?\b[0-9]{1,3}(?:,?[0-9]{3})*\.[0-9]{2}\b\)?
Hover over the expression here to have an explanation.
Upvotes: 3
Reputation: 1527
Try adding $
to the end of your regex, so you'll get
^\(?\d+\,?\d+[.]{1}\d{2}\)?$
That way you will at least only match numbers with exactly 2 digits after the .
and the string you mentioned, shouldn't match anymore.
Upvotes: 3