Optional characters in a regex

17,755

Solution 1

How about:

^[0-9+-]*[0-9][0-9+-]*$

This ensures that there is at least one digit somewhere in the string. (It looks like it might have a lot of backtracking, though. But on the other hand it doesn't have a + or * wrapped inside another + or *, which I don't like either.)

Solution 2

How about this:

([+-]?\d[+-]?)+

which means "one or more digits, each of which can be preceded or followed by an optional plus or minus".

Here's a Python test script:

import re
TESTS = "234654 24-3+-2 -234 25485+ ++--+".split()
for test in TESTS:
    print test, ":", re.match(r'([+-]?\d[+-]?)+', test) is not None

which prints this:

234654 : True
24-3+-2 : True
-234 : True
25485+ : True
++--+ : False

Solution 3

^([+-]*[0-9]+[+-]*)+$

Another solution using a positive look behind assertion ensuring there is at leat one number.

^[0-9+-]+$(?<=[0-9][+-]*)

Or using a positive look ahead assertion.

(?=[+-]*[0-9])^[0-9+-]+
Share:
17,755
Martin
Author by

Martin

Updated on June 05, 2022

Comments

  • Martin
    Martin almost 2 years

    The task is pretty simple, but I've not been able to come up with a good solution yet: a string can contain numbers, dashes and pluses, or only numbers.

    ^[0-9+-]+$
    

    does most of what I need, except when a user enters garbage like "+-+--+"

    I've not had luck with regular lookahead, since the dashes and pluses could potentially be anywhere in the string.

    Valid strings:

    1. 234654
    2. 24-3+-2
    3. -234
    4. 25485+

    Invalid:

    1. ++--+
  • 0x6adb015
    0x6adb015 almost 15 years
    But is 2+++5 legal? It is with your regex.
  • Ben S
    Ben S almost 15 years
    2+++5 should be legal from the description: "a string can contain numbers, dashes and pluses, or only numbers."
  • Jonathan Freeland
    Jonathan Freeland almost 15 years
    Well, the question doesn't mention anything about valid math expressions.
  • palantus
    palantus almost 15 years
    If it is math expressions he's aiming for, an expression tree would be much better than a regex. But I notice that * and / are not allowed, so I don't think it's supposed to be math.
  • ridgerunner
    ridgerunner about 13 years
    Almost good! The only problem is when you add anchors to this expression like so: ^([+-]?\d+[+-]?)+$ this will experience Catastrophic Backtracking when presented with a non-matching string like this: 01234567890123456789X The problem is that this is essentially: (\d+)+ which is a recipe for disaster for a backtracking regex engine. To fix this, simply remove the + from the \d+ like so: ^([+-]?\d[+-]?)+$ - which works beautifully. Fix it and you'll get my +1.
  • ridgerunner
    ridgerunner about 13 years
    ^([+-]*[0-9]+[+-]*)+$ will go pathological on non-matches (see my comment to Richies's solution). The ^[0-9+-]+$(?<=[0-9][+-]*) won't work because it uses variable length lookbehind (only .NET and JGSoft have that). (?=[+-]*[0-9])^[0-9+-]+ is ok but no need for the lookahead - just use ^[-+]*\d[\d+-]*$ directly.
  • ridgerunner
    ridgerunner about 13 years
    Your welcome. I've learned that it is most important to test for cases that don't match - that's where most of the problems lurk. +1