Regex for Only Numbers: Validate, Extract, and Calculate

Use a whole-input match with [0-9]+ to check for a nonempty digits-only input; to calculate with numbers in text, extract the matches, convert them to numbers, and perform the arithmetic in code. Checking whether a field contains only digits is different from removing letters or adding the numbers you find. The examples below cover Python and JavaScript, followed by signs, decimals, numeric ranges, and the edge cases that commonly break validation.

What “Only Numbers” Means in Regex

Regex matches text, not mathematical values. Before choosing a pattern, decide whether you need to:

  • Validate: Accept or reject the entire input.
  • Extract: Find numeric parts within mixed text.
  • Clean: Delete unwanted characters.
  • Calculate: Convert matched text into numeric values, then use arithmetic.

Removing nonnumeric characters is not the same as validating a number.

For example, removing everything except digits from -12.50 produces 1250. That may be useful when cleaning an identifier, but it changes a numeric value.

Also distinguish digits from numbers. A minus sign, decimal point, or exponent can belong to a number even though it is not a digit.

How to Validate, Extract, and Calculate Numbers With Regex

Choose the operation based on the result you actually need.

Goal Example Input Desired Result Operation
Check a digits-only field "1234" Valid Whole-input validation
Get the first digit sequence "Text#$1234" "1234" First match
Keep separate digit sequences "a12b7" ["12", "7"] Find all matches
Join every digit together "a12b7" "127" Replace nondigits with an empty string
Add the extracted values "a12b7" 19 Find, convert, then sum

Step 1: Define the Accepted Input

  1. Decide whether you are validating a complete field or searching within text. Finding digits somewhere in a string does not prove that the string contains only digits.
  2. Decide whether signs, decimal points, leading zeros, and whitespace are allowed. The basic examples here accept ASCII digits and preserve leading zeros.
  3. Decide what an empty result means. An empty field should fail digits-only validation; text without digit sequences should produce an empty match list.

Do not silently trim whitespace unless that is part of your input policy. If surrounding spaces are allowed, trim them before validation; otherwise, leave them in place so validation rejects the field.

Step 2: Run the Matching or Replacement Operation

  1. Use [0-9]+ to find a consecutive sequence of digits, the integer-search pattern used in the editor Aba Search & Replace. Here, [0-9] means an ASCII digit, and + means one or more occurrences; the pattern also matches zero and leading-zero strings.
  2. Use a whole-input operation for validation, all matches for extraction, or a nondigit replacement for cleanup.
  3. Check the returned result rather than assuming a match exists.

Python

import re
text = "qwerty1234uioo5678"
digit_pattern = r"[0-9]+"
matches = re.findall(digit_pattern, text)
first_match = matches[0] if matches else None
digits_only = re.sub(r"[^0-9]", "", text)
is_valid = re.fullmatch(digit_pattern, text) is not None
print(matches)      # ['1234', '5678']
print(first_match)  # 1234
print(digits_only)  # 12345678
print(is_valid)     # False

Python’s re.fullmatch() requires the entire string to match. It is a better fit for validation than re.search(), which succeeds if a matching substring exists anywhere.

JavaScript

const text = "qwerty1234uioo5678";
const matches = text.match(/[0-9]+/g) ?? [];
const firstMatch = matches[0] ?? null;
const digitsOnly = text.replace(/[^0-9]/g, "");
const isValid = text.length > 0 && !/[^0-9]/.test(text);
console.log(matches);     // ["1234", "5678"]
console.log(firstMatch);  // "1234"
console.log(digitsOnly);  // "12345678"
console.log(isValid);     // false

The JavaScript g flag finds or replaces every occurrence. Without it, these operations affect only the first match.

The validation expression deliberately checks for a nonempty string containing no nondigit characters. This avoids an anchor subtlety: in engines including Python and JavaScript, $ can match before a final newline. Multiline mode also changes anchor behavior, so do not enable it for whole-field validation.

Step 3: Convert Matches Before Calculating

  1. Extract separate numeric values instead of joining their digits.
  2. Convert each match to the required numeric type.
  3. Handle missing matches explicitly, then perform the calculation.

For a controlled input containing unsigned integers, this Python example calculates a total:

import re
text = "Items: 12 apples, 7 pears"
matches = re.findall(r"[0-9]+", text)
if not matches:
    raise ValueError("No integer values were found.")
values = [int(match) for match in matches]
total = sum(values)
print(values)  # [12, 7]
print(total)   # 19

The calculation is 12 + 7 = 19; joining the matches would instead create the string "127".

This extractor treats every digit sequence as a value, including digits inside identifiers. Use it only when that matches your input format. Never use eval() to calculate arbitrary user-supplied text.

Integer Regex Rules for Zeros, Signs, and Word Boundaries

Whole-input patterns accept integers with permitted signs and zeros, while word boundaries exclude values embedded in words.

Rejecting Leading Zeros

For a positive integer without a leading zero, [1-9][0-9]* is the search pattern used in Aba Search & Replace. The first digit must be nonzero; the remaining digits are optional.

Use it with whole-input validation when accepting a field. As a substring search, it can still find "7" inside "007".

To accept zero while rejecting leading-zero integers, the corresponding Aba Search & Replace pattern is [1-9][0-9]*|0. The | introduces an alternative: either a nonzero-leading positive integer or the single character 0.

With a whole-string match, this accepts "0" and "27" but rejects "00" and "027". For account numbers, ZIP codes, and other identifiers, leading zeros may be meaningful, keep those values as strings rather than converting them to integers.

Accepting Plus and Minus Signs

For optionally signed nonzero integers, with unsigned zero as a separate alternative, Aba Search & Replace uses [-+]?[1-9][0-9]*|0. The optional sign allows either + or -.

Applied to the whole input, that expression accepts "+27", "-27", and "0", but rejects "+0" and "-0" because the sign belongs only to the first alternative.

If signed zero should also be allowed, place the optional sign outside the alternatives:

[+-]?(?:0|[1-9][0-9]*)

Use this with a full-match operation. It still rejects leading-zero forms such as "007".

Checking the Whole Integer Input

For a complete integer field allowing negative values but not an explicit plus sign, Aba Search & Replace uses:

^(-?[1-9][0-9]*|0)$

The parentheses keep both alternatives inside the start and end anchors. Without grouping, an expression such as ^[1-9][0-9]*|0$ applies the start anchor only to the first branch and the end anchor only to the second.

This integer format permits ordinary negative integers, positive integers, and unsigned zero. It excludes leading zeros, decimal points, and signed zero.

In Python, use the unanchored inner expression with re.fullmatch() for strict whole-input checking:

import re
value = "-27"
is_valid = re.fullmatch(r"-?[1-9][0-9]*|0", value) is not None
print(is_valid)  # True

Excluding Numbers Inside Words

For integer searches that exclude values embedded in words such as 600px and x64, Aba Search & Replace uses \b(-?[1-9][0-9]*|0)\b.

A word boundary marks a transition between word and nonword characters. That helps exclude adjacent letters, but it is not a complete definition of a numeric token:

  • Decimal points can create word boundaries, so parts of a decimal may still match.
  • A leading minus sign may be omitted. At the start of -27, there is no word boundary before the minus, but there is one between the minus and the digit.
  • Underscores count as word characters in common regex engines.

Regex for Decimals, Scientific Notation, and Hexadecimal

Preserve the syntax that determines a number’s value, then convert the complete match.

Decimal and scientific-notation validation needs more than a digits-only pattern. It also needs a clear policy for signs, leading zeros, and forms such as .5 or 5..

Decimal Fractions

For fractional-number searches, Aba Search & Replace uses \b-?(?:[1-9][0-9]*(?:\.[0-9]+)?|\.[0-9]+|0)\b.

That expression includes a branch intended for fractions beginning with a decimal point, but its surrounding word boundaries make it unsuitable as a universal decimal extractor. It can lose a leading sign or decimal point, and it does not capture 0.5 as one complete value.

For whole-input validation, this Python version handles those cases explicitly:

import re
value = ".5"
pattern = r"[+-]?(?:[0-9]+(?:\.[0-9]+)?|\.[0-9]+)"
is_valid = re.fullmatch(pattern, value) is not None
print(is_valid)  # True

This accepts integers, signed values, leading-zero values, ordinary decimals, and fractions beginning with a dot. It rejects a trailing decimal point such as "5.", a lone dot, and commas.

The escaped dot \. matches a literal decimal point. An unescaped . normally matches almost any character.

Scientific Notation

For floating-point searches with an optional exponent, Aba Search & Replace uses \b-?(?:[1-9][0-9]*(?:\.[0-9]+)?|\.[0-9]+|0)(?:[eE][+-]?[0-9]+)?\b.

The exponent portion accepts an e or E, an optional sign, and one or more digits. For example, it supports the exponent in 5.2777e+231.

A strict Python validator can instead use:

import re
value = "5.2777e+231"
pattern = r"[+-]?(?:[0-9]+(?:\.[0-9]+)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?"
is_valid = re.fullmatch(pattern, value) is not None
print(is_valid)  # True

This accepts ordinary decimal values as well as scientific notation. It rejects incomplete exponents such as "5e" and "5e+".

Syntax validation does not guarantee that a value fits the numeric type you will use. Check range and finiteness after conversion when your application requires them.

Hexadecimal Values

For combined decimal, exponent, and hexadecimal searches, Aba Search & Replace uses \b-?(?:[1-9][0-9]*(?:\.[0-9]+)?|\.[0-9]+|0(?:x[0-9a-fA-F]+)?)(?:[eE][+-]?[0-9]+)?\b.

That combined form recognizes a lowercase 0x prefix, but it also shares an optional decimal exponent across the alternatives. It is not a universal programming-language numeric-literal validator.

In application code, keeping hexadecimal validation separate makes the accepted syntax and conversion unambiguous:

import re
value = "0x2A"
if re.fullmatch(r"[+-]?0[xX][0-9a-fA-F]+", value) is None:
    raise ValueError("Invalid hexadecimal integer.")
number = int(value, 16)
print(number)  # 42

This accepts either case for the prefix and hexadecimal letters, then converts using base 16. It does not attempt to support language-specific hexadecimal floating-point syntax.

Regex for Numeric Ranges

Regex operates on characters, so 1-10 matches the literal text 1-10; it does not mean “a number between one and ten.” Numeric-range patterns work by splitting the allowed values into digit-length and prefix cases.

Integers From 1 Through 20

Use ([1-9]|1[0-9]|20) with a full-match operation, or this anchored form where the engine’s anchor behavior fits your input:

^([1-9]|1[0-9]|20)$

The alternatives cover a nonzero single digit, a two-digit value beginning with 1, or the upper endpoint. Whole-input matching prevents an otherwise valid substring from being accepted inside a larger value.

Integers From 0 Through 255

Use ([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) with a full-match operation. Its anchored form is:

^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$

The alternatives cover single-digit values, two-digit values without a leading zero, and progressively narrower three-digit prefixes. Signs, decimals, and leading-zero forms are excluded.

Comparing Values in Code

When your application can perform numeric comparisons, validating syntax and then comparing the converted value is usually easier to maintain:

import re
value = "200"
has_valid_syntax = re.fullmatch(r"0|[1-9][0-9]*", value) is not None
is_valid = has_valid_syntax and 0 <= int(value) <= 255
print(is_valid)  # True

The short-circuiting and prevents conversion when the syntax is invalid. This approach also keeps a changing business range out of a complicated regex.

How to Test a Numbers-Only Regex

Test both accepted and rejected inputs in the language or application that will actually run the expression. A tester using a different engine or flags can give misleading results.

For a nonempty ASCII digits-only validator that allows leading zeros, use these checks:

Input Expected Result What It Tests
"1234" Accept Ordinary digits
"007" Accept Leading-zero policy
"" Reject Empty input
" 1234 " Reject Whitespace policy
"1234\n" Reject Final-newline handling
"-12.5" Reject Signs and decimal points
"abc1234" Reject Whole-input validation
"١٢٣" Reject Non-ASCII decimal digits

Before using the result:

  • Confirm that extraction returns separate matches when you need separate values.
  • Confirm that no-match input is handled deliberately.
  • Confirm that numeric conversion preserves the information you need.
  • Confirm that decimals, separators, and exponents follow one defined input format.
  • Keep validation on the server or processing boundary, even if the interface also filters input.

Add these cases to automated tests, then run them against the exact regex engine and flags used by your application.

Frequently Asked Questions

Does \d Always Mean the Same Thing as [0-9]?

No. [0-9] explicitly means ASCII digits, while \d is engine-dependent: Python’s default string patterns and .NET normally include Unicode decimal digits, whereas JavaScript’s \d matches ASCII digits. Choose the form that matches your data requirements rather than assuming they are interchangeable everywhere.

How Do I Find Integers Without Matching Parts of Negative or Decimal Values?

For text that treats signs, dots, letters, and underscores as part of numeric tokens, this Python pattern extracts unsigned integers without taking digit fragments from negative or decimal values:

import re
text = "Values: 12, -7, 3.5, x64"
matches = re.findall(r"(?<![\w.+-])[0-9]+(?![\w.])", text)
print(matches)  # ['12']

It also rejects plus-prefixed values and integers directly touching a period, including sentence-ending punctuation. If periods can be either decimal marks or punctuation in your input, define that distinction before choosing an extractor.

Can Regex Select Only Numbers Within a Previous Selection?

Yes, if the editor or application supports searching within selected text. Enable its selection-only search scope before running the digit pattern; a regex normally does not know which text you highlighted. In code, pass only the selected substring to the matching function, and adjust match positions by the selection’s starting offset if you need positions in the original text.