During researches for a regex that matches an IP address accurately I found this article which is the first result on google. The article shows a regular expression for accurate matching but it is not correct: It doesn’t respect, that a leading zero in a component of the IP marks that the component should be interpreted as an octal number.

For example it matches:

1.095.1.1

as a valid IP. But 95 isn’t a valid octal number!

Knowing this, I started to craft my own regex which should respect this. In it’s first version it will simply reject octal numbers as component. This lead me to the following pattern:

<?php
$pattern = '/^((^|\.)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}$/';

The pattern works a bit different than the regex shown in that article, while the article defines an IP addess as a series of 3 numbers followed by a dot . plus another number, this pattern defines the IP address as a series of 4 numbers which are optionally preceded by a dot . or the start of the string. This makes the regex pattern itself much shorter and simpler.

Explanation:

The regex requires that each part of the IP will start with a dot . or the beginning of the string ^ (which is true for the first component):

(^|\.)

Each component needs to be in one of the following ranges:

  • 1[0-9]{2} range: 100 – 199
  • [1-9][0-9] range: 10 – 99
  • [0-9] range: 0 – 9
  • 2[0-4][0-9] range: 200 – 249
  • 25[0-5] range: 250 – 255

Test:

The following scripts tests if the regex matches valid IP addresses and rejects invalid ones:

<?php

$pattern = '/^((^|\.)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}$/';

foreach(array(
    '10.23.34.2',
    '0.0.0.0',
    '127.0.0.1',
    '255.255.255.0',
    '192.168.0.1',
    '1.1.1.1'
) as $ip) {
    if(!preg_match($pattern, $ip, $m)) {
        echo "$ip FAILED\n";
    }   
}

foreach(array(
    '10.23.343.2',
    '0.0.0',
    '127.0.0.1.2',
    'test',
    '256.256.34.5',
    '10.01.02.3'
) as $ip) {
    if(preg_match($pattern, $ip, $m)) {
        echo "$ip FALSE POSITIVE\n";
    }   
}

Leave a Reply