Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: Using a regex to remove decimals out of IP address

Tags:

regex

php

mysql

I currently have a liking function on my images site that stores user IPs in the database against unique $imgids.

The IPs are currently stored as strings. To save space, I'd like to store the IPs not as strings with decimal points, but as 32-bit integers (1 bit per integer vs 1 byte per char in the string). I think this could save considerable space because I have the potential for n unique IPs to like x images...

So given string "109.181.156.221" that'd be a max of 12 bytes for the numbers, + 3 bytes per decimal point... so 15 bytes * 5000 IPs * 10 image IDs = 7.1 Mb

Versus 32bit 109181156221, 4 bytes * 5000 IPs * 100 image IDs = 2 Mb

So, before I inser the IP, I'd like to use a regex to remove decimals, and then store the IP as a number... "109.181.156.221" -> 109181156221 I'm new to Regexs, but I've tried this, but it won't work:

$ipINT = preg_replaceAll("\\.+$", "" , $ipString);

So my questions are:

1) Would the space savings even matter in a Mysql database? Is this worth the trouble?

2) Where am I off with my regex?

3) Would I be able to convert it back if I'm trying to read it?

Any thoughts?

Thanks!

like image 984
user3871 Avatar asked Jan 14 '23 03:01

user3871


2 Answers

There are different ways to do this:

The right way:

By letting the database do the conversion for you. You have to store the ip in the database as INT(10) UNSIGNED and use INET_ATON & INET_NTOA:

SELECT INET_ATON("109.181.156.221"); // result 1840618717
SELECT INET_NTOA("1840618717"); // result 109.181.156.221

The alternative way:

By using PHP internal functions ip2long() & long2ip() and then store it in the DB:

$ipINT = ip2long('109.181.156.221'); // result 1840618717
$ip = long2ip('1840618717'); // result 109.181.156.221

The non-standard way:

By removing the dots and adding "0" if needed to be able to convert it back:

function ip2int($ip){
  $chunks = explode(".", $ip);
  $int = '';
  foreach($chunks as $chunk){
    $int .= str_pad($chunk, 3, '0', STR_PAD_LEFT);
  }
  return $int;
}

function int2ip($int){
  $chunks = str_split($int, 3);
  $c = count($chunks);
  $ip = ltrim($chunks[0], '0');
  for($i=1;$i<$c;$i++){
    $ip .= '.' . ltrim($chunks[$i], '0');
  }
  return($ip);
}

echo ip2int("109.1.156.5") . '<br>'; // result 109001156005
echo int2ip("109001156005"); // result 109.1.156.5

Fixing your RegEx:

$ip = "109.181.156.221";
$replace = preg_replace("/\./", "", $ip); // This will remove all the dots
echo $replace; // result 109181156221
like image 87
HamZa Avatar answered Jan 17 '23 18:01

HamZa


You can use ip2long(), then it should fit in an unsigned int column.

like image 24
Josh Avatar answered Jan 17 '23 17:01

Josh