Home >Learn

Regex for Numbers Only: Patterns and Validation Examples (2026)

Published Updated

The naive pattern and why it fails

Most people start with

\d+
. It matches digits, sure. But used with
preg_match
or
search()
, it also matches "42" inside "abc42xyz". If you want the whole input to be numbers only, the pattern needs anchors:

^\d+$

The caret anchors to the start, the dollar sign to the end. Now "42" passes and "abc42" fails. This is the single most common fix in number validation.

Allow an optional sign

Integers can be negative. Wrap the sign in a group with a question mark:

^-?\d+$

The

-?
means zero or one minus sign. If you also want to accept an explicit plus, use
^[+-]?\d+$
.

Add decimals without breaking integers

The classic mistake is

^\d+\.\d+$
, which rejects "42" because it requires a decimal point. Make the fractional part optional:

^-?\d+(\.\d+)?$

Now "42", "-7", "3.14" all pass. But "42." still fails, which is usually the behavior you want.

Allow thousand separators

Locale formatting throws a new wrinkle. "1,234.56" needs commas handled:

illustration for Regex for Numbers Only: Patterns and Val
^-?\d{1,3}(,\d{3})*(\.\d+)?$

The

\d{1,3}
allows up to three leading digits, and
(,\d{3})*
matches every following group of three. Swap commas for dots if you target European formats, but never accept both in the same pattern, that is how "1,234.56" and "1.234,56" get mixed up.

Practical validators

US phone numbers, digits only:

^[0-9]{10}$

Postal code with an optional extension:

^\d{5}(-\d{4})?$

Amount with two fixed decimals and no sign:

^\d+(\.\d{2})?$

Testing your pattern before you ship it

Write a test list, not just one happy case. For the decimal pattern above, test "42", "-7", "3.14", "42.", ".5", "-", and "1,234". A regex toolbox with a live match panel makes this fast: paste the pattern, paste the cases, and confirm each one flips correctly. Then copy the pattern into your code and keep the test list in your repo.

The traps worth remembering

Missing anchors let partial matches slip through. Optional decimals reject nothing but whole numbers. Locale separators are a feature, not a bug, once you pick one format. And

\d
is not always ASCII: in some engines it matches Unicode digits too. If you want strict 0-9, write
[0-9]
explicitly.

Table of Contents

Information

  • Hits6
  • Published date2026/10/05
0/500
Share your thoughts respectfully.

More Posts

Explore more articles from this section
Feedback email