More Regular Expressions: Regex for IP v4 Addresses

I’ve seen some posts suggesting this as a useful IPv4 Regex:

\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

This matches four groups of between 1-3 digits, with each group separated by a dot.

An obvious enhancement here would be to remove some redundancy:

(\d{1,3}\.){3}\.\d{1,3}  

or  

\d{1,3}(\.\d{1,3}){3}

These are both shorter and say the same thing.  However, there’s unfortunately an issue  with correctness.  These Regexs match IPv4 addresses, but they also match strings that aren’t valid IPv4 addresses.  The following will match, for example:

999.999.999.999

What to do?  Well, as mentioned previously, start with Jeffrey Friedl’s book “Mastering Regular Expressions”, 3rd Edition, O’Reilly, ISBN: 978-0-596-52812-6 from Amazon or directly from O’Reilly.  Read the customer reviews on these sites to see what I mean.

Otherwise, there are several good Regex generation/authoring programs out there.  I have used Jan Goyvaerts’ RegexBuddy for a long time and unconditionally recommend it.  It’s not free but I would say it’s a very worthwhile investment of 30 Euros if you intend to use regex to any degree.  Even without the program itself just the help files are great.  You can get your money back up to 3 months after purchase if you’re not happy, so try it!

If these two options don’t appeal to you then it’s off to the web.  Sadly, there’s lots and lots of dross and rubbish out there, some of it wildly misleading.

Valid Formats

To cut a long story short, match IPv4 address with this:

\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3} (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

Or this:

\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b

Or this:

\b(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}\b

These all match valid IPv4 addresses without inadvertently matching other things.

Breakdown

There are two things that can help understanding of complex regexs: using intermediate patterns and using extended mode.

PowerShell can save intermediate patterns (or parts of a regex) in variables that can later be uses in a more complex string, using standard variable expansion. 

Using regex ‘Extended Mode’ allows a regex pattern to be split across lines (and to use white space and comments) and is indicated by using ‘(?x)’ at the beginning of the regex pattern.  This can be combined with a here-string to allow the regex to be more easily visualised…

Using these facilities we can break down those IPv4 regexs to something a little more comprehensible (note, I’ve used the ${xxxx} format for variable names here to save spelling out $TwoHundredToTwoFiveFive).

An IPv4 address is made up of 4 Octets – each with a value between 0 and 255.  To specify this in a regex we break the range down into 3 groups (divide and conquer), specifically 0-199, 200-249 and 250-255.  Remember that ‘[0-4]’ matches a single character (one of 0,1,2,3,4).   We then say that an Octet is either one of these by using an ( x | y | z ) alternation.  We build up the final address by inserting dots between 4 of these Octets.

Here’s the result.  Tidy and (hopefully!) comprehensible :-)

${250-255}=’25[0-5]’   # Matches 3 digit numbers between 250 and 255
${200-249}=‘2[0-4]\d’  # Matches 3 digit numbers between 200 and 249
${0-199}=‘[01]?\d\d?’  # Matches 1, 2 or 3 digit numbers between 0 and 199

$Octet=“( ${250-255} | ${200-249} | ${0-199} )”

$IPv4=@”
(?x) ^

$Octet (\.$Octet){3}

$

“@

 

IPv4 Function

Here’s a quick PowerShell function that will return the first valid IPv4 address from a given string (or $Null if the string doesn’t contain a valid address):

Extract IP Address from String
  1. # Extract an IP address from a string and return it.  Return $Null if no valid address found.
  2. # (If the string contains more than one valid address only the first one will be returned)
  3. Function ExtractValidIPAddress($String){
  4.     $IPregex=‘(?<Address>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))’
  5.     If ($String -Match $IPregex) {$Matches.Address}
  6. }

Thus:

C:\PS> ExtractValidIPAddress ‘This is a string with an IPv4 address 192.168.0.1 in it’
192.168.0.1