Matching numbers with regular expressions — only digits and commas

前端 未结 10 1470
旧时难觅i
旧时难觅i 2020-11-22 08:07

I can\'t figure out how to construct a regex for the example values:

123,456,789
-12,34
1234
-8

Could you help me?

相关标签:
10条回答
  • 2020-11-22 08:38

    Try this:

    ^-?\d{1,3}(,\d{3})*(\.\d\d)?$|^\.\d\d$
    

    Allows for:

    1
    12
    .99
    12.34 
    -18.34
    12,345.67
    999,999,999,999,999.99
    
    0 讨论(0)
  • 2020-11-22 08:39

    For the examples:

        ^(-)?([,0-9])+$
    

    It should work. Implement it in whichever language you want.

    0 讨论(0)
  • 2020-11-22 08:40

    Try this:

    ^-?[\d\,]+$
    

    It will allow an optional - as the first character, and then any combination of commas and digits.

    0 讨论(0)
  • 2020-11-22 08:41

    Since this question has been reopened four years later, I'd like to offer a different take. As someone spends a lot of time working with regex, my view is this:

    A. If Possible, Don't Use Regex To Validate Numbers

    If at all possible, use your language. There may be functions to help you determine if the value contained by a string is a valid number. That being said, if you're accepting a variety of formats (commas, etc.) you may not have a choice.

    B. Don't Write the Regex Manually to Validate a Number Range

    • Writing a regex to match a number in a given range is hard. You can make a mistake even writing a regex to match a number between 1 and 10.
    • Once you have a regex for a number range, it's hard to debug. First, it's awful to look at. Second, how can you be sure it matches all the values you want without matching any of the values you don't want? Frankly, if you're by yourself, without peers looking over your shoulder, you can't. The best debugging technique is to output a whole range of numbers programmatically and check them against the regex.
    • Fortunately, there are tools to generate a regex for a number range automatically.

    C. Spend your Regex Energy Wisely: Use Tools

    • Matching numbers in a given range is a problem that has been solved. There's no need for you to try to reinvent the wheel. It's a problem that can be solved mechanically, by a program, in a way that is guaranteed to be error-free. Take advantage of that free ride.
    • Solving a number-range regex may be interesting for learning purposes a couple of times. Beyond that, if you have energy to invest in furthering your regex skills, spend it on something useful, such as deepening your understanding of regex greed, reading up on Unicode regex, playing with zero-width matches or recursion, reading the SO regex FAQ and discovering neat tricks such as how to exclude certain patterns from a regex match... or reading classics such as Matering Regular Expressions, 3rd Ed or The Regular Expressions Cookbook, 2nd Ed .

    For tools, you can use:

    • Online: Regex_for_range
    • Offline: the only one I'm aware of is RegexMagic (not free) by regex guru Jan Goyvaerts. It's his beginner regex product, and as I recall it has a great range of options for generating numbers in a given range, among other features.
    • If the conditions are too complex, auto-generate two ranges... then join them with an alternation operator |

    D. An Exercise: Building a Regex for the Specs in the Question

    These specs are quite wide... but not necessarily vague. Let's look at the sample values again:

    123,456,789
    -12,34
    1234
    -8
    

    How do the first two values relate? In the first, the comma matches groups of powers of three. In the second, it probably matches the decimal point in a continental-European-style number format. That does not mean we should allow digits everywhere, as in 1,2,3,44. By the same token, we shouldn't be restrictive. The regex in the accepted answer, for instance, will not match one of the requirements, 123,456,789 (see demo).

    How do we build our regex to match the specs?

    • Let's anchor the expression between ^ and $ to avoid submatches
    • Let's allow an optional minus: -?
    • Let's match two types of numbers on either side of an alternation (?:this|that):
    • On the left, a European-style digit with optional comma for decimal part: [1-9][0-9]*(?:,[0-9]+)?
    • On the right, a number with thousands separators: [1-9][0-9]{1,2}(?:,[0-9]{3})+

    The complete regex:

    ^-?(?:[1-9][0-9]*(?:,[0-9]+)?|[1-9][0-9]{1,2}(?:,[0-9]{3})+)$
    

    See demo.

    This regex does not allow European-style numbers starting with 0, such as 0,12. It's a feature, not a bug. To match those as well, a small tweak will do:

    ^-?(?:(?:0|[1-9][0-9]*)(?:,[0-9]+)?|[1-9][0-9]{1,2}(?:,[0-9]{3})+)$
    

    See demo.

    0 讨论(0)
提交回复
热议问题