27

I need a regex to match both, integer values aswell as float numbers (whereas float numbers have a "." as seperator). Those numbers are always in a bracket and may have a leading "+".

What should be valid:

  • (1.0)
  • (1)
  • (9.9)
  • (10000000)
  • (+15)

What should be invalid:

  • 1.0 --- because no bracket
  • 5 --- because no bracket
  • (1,5) --- becaue "," instead of "."
  • (a) --- because of not a number
  • (1 5) --- because of not only one number
  • (1+5) --- because... well... just failing the pattern
  • [5] --- because wrong brackets
user2015253
  • 1,263
  • 4
  • 14
  • 25

3 Answers3

56

This should work on most perl like regex engines:

/(\d+(?:\.\d+)?)/
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
ennuikiller
  • 46,381
  • 14
  • 112
  • 137
25

Unfortunately, the currently accepted answer is flawed (it will match "1a5", but it won't match ".5"). So I decided to write my own Regex, as well as a cheap Perl script to test it.

Requirements

The Regex will match an integer or float, with a preceding +/- sign. I don't care for E notation, so I ignored it.
nhahtdh mentioned "(5.) and (.6)": "5." does not look right to me, the trailing period has no purpose. However, ".6" is indeed valid, as the leading period indicates a positive value < 1 (i.e., it's short for "0.6").
The initial (?=.) is to make sure a blank string won't match.
As a bonus, I used nested groups, so that you can easily extract the different parts of the number:

  • $1 = The whole number
  • $2 = Integer part
  • $3 = Fractional part with leading period
  • $4 = Fractional part

Regex

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

Test

$ perl -e 'use strict; use warnings; my $a = "1.0"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<1.0>
Integer:<1>
Fraction:<0>
$ perl -e 'use strict; use warnings; my $a = "1"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<1>
Integer:<1>
No fraction
$ perl -e 'use strict; use warnings; my $a = "9.9"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<9.9>
Integer:<9>
Fraction:<9>
$ perl -e 'use strict; use warnings; my $a = "10000000"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<10000000>
Integer:<10000000>
No fraction
$ perl -e 'use strict; use warnings; my $a = "+15"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<+15>
Integer:<15>
No fraction
$ perl -e 'use strict; use warnings; my $a = "1,5"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH
$ perl -e 'use strict; use warnings; my $a = "a"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH
$ perl -e 'use strict; use warnings; my $a = "1 5"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH
$ perl -e 'use strict; use warnings; my $a = "1+5"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH
$ perl -e 'use strict; use warnings; my $a = "5."; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH
$ perl -e 'use strict; use warnings; my $a = ".6"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<.6>
Integer:<>
Fraction:<6>
$ perl -e 'use strict; use warnings; my $a = ".5"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
MATCH
Float:<.5>
Integer:<>
Fraction:<5>
$ perl -e 'use strict; use warnings; my $a = "1a5"; if ($a =~ /^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$/) { print "MATCH\nFloat:<$1>\n"; print defined $2 ? "Integer:<$2>\n" : "No integer\n"; print defined $4 ? "Fraction:<$4>\n" : "No fraction\n"; } else { print "NO MATCH\n"; }'
NO MATCH

Please let me know if there's something that I have overlooked.

Addition

Enforcing braces is trivial, just wrap the whole thing in ESCAPED parentheses:

^\((?=.)([+-]?([0-9]*)(\.([0-9]+))?)\)$
basic6
  • 3,643
  • 3
  • 42
  • 47
-1

I'm not sure, but I don't think the accepted answer will accept .6.

my $float = qr/(\([-+]?\d*\.?\d+\))/;
my $test = "this is my +15.8 (-17.3) 0.9 (8) .7 -.6 string"
    . "(+5.8) -6.3 (0.9) 8 (.9) (-.16)";

while ($test =~ /$float/g) {
    printf("<$1>\n");
}

I stole this pattern from someplace. Maybe https://www.regular-expressions.info/floatingpoint.html.

<(-17.3)>
<(8)>
<(+5.8)>
<(0.9)>
<(.9)>
<(-.16)>

UPDATE: Added parens.

Erik Bennett
  • 1,049
  • 6
  • 15