dtx
dtx

Reputation: 340

Regular Expression for numbers unless all digits are identical

I need help to write a regular expression to match numbers which may be broken up into sections by spaces or dashes e.g:

606-606-606
606606606
123 456-789

However, matches should be rejected if all the digits of the number are identical (or if there are any other characters besides [0-9 -]):

111 111 111
111111111
123456789a

If spaces/dashes weren't allowed, the Regex would be simple:

/^(\d)(?!\1*$)\d*$/

But how would I allow dashes and spaces in the number?

EDIT

How would I allow also letters in the same regex (dashes and spaces shoud be still allowed) e.g:

aaaaa - it's not ok

aa-aaa-aaa-aaaaa - it's not OK

ababab - it's OK

ab-ab-ab - it's OK

This rule checks only numbers.

^(?!(?:(\d)\1+[ -]*)+$)\d[\d- ]+$

Upvotes: 1

Views: 153

Answers (2)

martinstoeckli
martinstoeckli

Reputation: 24071

Even if you can, i wonder if a regex is the right tool to solve this problem. Just imagine your fellow developers scratching their heads trying to understand your code, how much time do you grant them? Even worse, what if you need to alter the rules?

A small function with some comments could make them happy...

function checkNumberWithSpecialRequirements($number)
{
    // ignore given set of characters
    $cleanNumber = str_replace([' ', '-'], '', $number);

    // handle empty string
    if ($cleanNumber == '')
        return false;

    // check whether non-digit characters are inside
    if (!ctype_digit($cleanNumber))
        return false;

    // check if a character differs from the first (not all equal)
    for ($index = 1; $index < strlen($cleanNumber); $index++)
    {
        if ($cleanNumber[$index] != $cleanNumber[0])
            return true;
    }
    return false;
}

Upvotes: 0

revo
revo

Reputation: 48711

Desired results can be achieved by this Regular Expression:

^(?!(?:(\d)\1+[ -]*)+$)\d[\d- ]+$

Live demo

Explanations:

^               # Start of string
(?!             # Negative Lookahead to check duplicate numbers
    (?:         # Non-capturing group
        (\d)    # Capture first digit
        \1+     # More digits same as lately captured one
        [ -]*   # Any spaces and dashes between
    )+          # One or more of what's captured up to now
    $           # End of string
)               # End of negative lookahead
\d              # Start of match with a digit
[\d- ]+         # More than one digit/dash/space
$               # End of string

The theory behind this regex is to use a lookaround to check if string contains any duplicate numbers base on the first captured number. If we have no match in this lookaround, then match it.

Upvotes: 2

Related Questions