19

I need a regex expression that will match the following:

.5
0.5
1.5
1234

but NOT

0.5.5
absnd (any letter character or space)

I have this that satisfies all but 0.5.5

^[.?\d]+$
Oded
  • 489,969
  • 99
  • 883
  • 1,009
clestbest
  • 237
  • 1
  • 3
  • 11
  • 1
    The best answer, rather a research article is here: https://stackoverflow.com/a/39399503/715269 – Gangnus Jul 28 '17 at 13:05

5 Answers5

40

This is a fairly common task. The simplest way I know of to deal with it is this:

^[+-]?(\d*\.)?\d+$

There are also other complications, such as whether you want to allow leading zeroes or commas or things like that. This can be as complicated as you want it to be. For example, if you want to allow the 1,234,567.89 format, you can go with this:

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

That \b there is a word break, but I'm using it as a sneaky way to require at least one numeral at the end of the string. This way, an empty string or a single + won't match.

However, be advised that regexes are not the ideal way to parse numeric strings. All modern programming languages I know of have fast, simple, built-in methods for doing that.

Justin Morgan - On strike
  • 30,035
  • 12
  • 80
  • 104
  • 2
    It seems we have a troll around these parts. I got downvoted too. – Tyler Crompton Jun 06 '12 at 20:05
  • 2
    It gets a bit sketch when you account for thousands separators since some countries swap the period and commas. – Tyler Crompton Jun 06 '12 at 20:28
  • @TylerCrompton - [Believe me, I know.](http://stackoverflow.com/a/5917250/399649) Like I said, as complicated as you want it to be. – Justin Morgan - On strike Jun 06 '12 at 20:37
  • Why doesn't changing the final "+" to "*" allow for a trailing "."? "2.", "+1." etc https://regex101.com/r/O3eyny/1 – Sam Dean Nov 01 '19 at 16:05
  • Sorry, seen the bit about "\b". How could I modify it to allow a trailing "." whilst continuing to prevent empty strings and single "+"/"-" triggering it. Should I ask a new question? – Sam Dean Nov 01 '19 at 16:44
  • @SamDean - I would suggest a new question, mostly because there are lots of potential variations and I would need specifics. You could take a look at [my other answer as well.](http://stackoverflow.com/a/5917250/399649) – Justin Morgan - On strike Nov 03 '19 at 03:21
16

Here's a much simpler solution that doesn't use any look-aheads or look-behinds:

^\d*\.?\d+$

To clearly understand why this works, read it from right to left:

  • At least one digit is required at the end.
    7 works
    77 works
    .77 works
    0.77 works
    0. doesn't work
    empty string doesn't work
  • A single period preceding the digit is optional.
    .77 works
    77 works
    ..77 doesn't work
  • Any number of digits preceding the (optional) period. .77 works
    0.77 works
    0077.77 works
    0077 works

Not using look-aheads and look-behinds has the added benefit of not having to worry about RegEx-based DOS attacks.

HTH

Spike Sagal
  • 191
  • 1
  • 4
13

Nobody seems to be accounting for negative numbers. Also, some are creating a capture group which is unnecessary. This is the most thorough solution IMO.

^[+-]?(?:\d*\.)?\d+$
Tyler Crompton
  • 12,284
  • 14
  • 65
  • 94
3

The following should work:

^(?!.*\..*\.)[.\d]+$

This uses a negative lookahead to make sure that there are fewer than two . characters in the string.

http://www.rubular.com/r/N3jl1ifJDX

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
1

This could work:

^(?:\d*\.)?\d+$
niko
  • 1,816
  • 13
  • 13