Oops! --#-- OK, here's a flaw: Our match string accepts commas optionally, as long as they're aligned along the 3-digit boundaries. In other words, it'll match 999999,999 and 99999,999999999 and so forth. But it won't accept 999,99,999.

You may decide to live with such a small thing, but before you do, consider the remedy.

if ($string_to_test =~ m/^\d{0,3},(\d{3},)*\d{3}(\.\d{2})?$|^\d*(\.\d{2})?$/) { do something here... }
See that? We now have two alternate matching patterns, separated by the '|' character. The second alternative is simple -- just digits. But note that the commas are no longer optional in the first alternative.

What about negative numbers? Easy, add optional parentheses or a minus sign (alternate matches again). Be sure to escape the minus and the opening and closing parentheses with backslashes.

Enough. What next, names? Too easy. Let's do dates.