PHP:使用正则表达式从IP地址中删除小数

时间:2021-04-23 16:50:36

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

我目前在我的图像站点上有一个喜欢的功能,它将数据库中的用户IP存储在唯一的$ 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...

IP当前存储为字符串。为了节省空间,我想将IP不是作为带小数点的字符串存储,而是存储为32位整数(每个整数1位,而字符串中每个字符1个字节)。我认为这可以节省相当大的空间,因为我有可能n个独特的IP喜欢x图像......

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

所以给定字符串“109.181.156.221”,数字最多为12个字节,每个小数点数为+ 3个字节...所以15个字节* 5000个IP * 10个图像ID = 7.1 Mb

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

对比32位109181156221,4个字节* 5000个IP * 100个图像ID = 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:

因此,在我使用IP之前,我想使用正则表达式删除小数,然后将IP存储为数字......“109.181.156.221” - > 109181156221我是Regexs的新手,但我已经试过这个,但它不会起作用:

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

So my questions are:

所以我的问题是:

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

1)在Mysql数据库中节省空间是否也很重要?这值得吗?

2) Where am I off with my regex?

2)我的正则表达式在哪里?

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

3)如果我想读它,我能将它转换回来吗?

Any thoughts?

Thanks!

4 个解决方案

#1


3  

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:

让数据库为您进行转换。您必须将IP作为INT(10)UNSIGNED存储在数据库中,并使用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:

通过使用PHP内部函数ip2long()&long2ip(),然后将其存储在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:

通过删除点并添加“0”,如果需要能够将其转换回来:

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

#2


4  

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

你可以使用ip2long(),然后它应该适合unsigned int列。

#3


2  

Use the ip2long() function to store IP addresses - Unsigned INT(10) should be great.

使用ip2long()函数存储IP地址 - 无符号INT(10)应该很棒。

Use long2ip() to decode.

使用long2ip()进行解码。

http://php.net/manual/en/function.ip2long.php

Your solution wouldn't work for IP Address like 1.123.123.123, as you wouldn't know where to restore the decimal point. The correct way to store an IP address would be with the method described above.

您的解决方案不适用于1.123.123.123之类的IP地址,因为您不知道在哪里恢复小数点。存储IP地址的正确方法是使用上述方法。

#4


0  

if you want to extract only digits you dont need regex you can just use:

如果你只想提取你不需要正则表达式的数字,你可以使用:

filter_var('109.181.156.221', FILTER_SANITIZE_NUMBER_INT);

will give you 109181156221

会给你109181156221

but i dont think you would be able to convert it back to IP form.

但我不认为你能将它转换回IP形式。

I would store it with dots.

我会用点存储它。

#1


3  

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:

让数据库为您进行转换。您必须将IP作为INT(10)UNSIGNED存储在数据库中,并使用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:

通过使用PHP内部函数ip2long()&long2ip(),然后将其存储在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:

通过删除点并添加“0”,如果需要能够将其转换回来:

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

#2


4  

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

你可以使用ip2long(),然后它应该适合unsigned int列。

#3


2  

Use the ip2long() function to store IP addresses - Unsigned INT(10) should be great.

使用ip2long()函数存储IP地址 - 无符号INT(10)应该很棒。

Use long2ip() to decode.

使用long2ip()进行解码。

http://php.net/manual/en/function.ip2long.php

Your solution wouldn't work for IP Address like 1.123.123.123, as you wouldn't know where to restore the decimal point. The correct way to store an IP address would be with the method described above.

您的解决方案不适用于1.123.123.123之类的IP地址,因为您不知道在哪里恢复小数点。存储IP地址的正确方法是使用上述方法。

#4


0  

if you want to extract only digits you dont need regex you can just use:

如果你只想提取你不需要正则表达式的数字,你可以使用:

filter_var('109.181.156.221', FILTER_SANITIZE_NUMBER_INT);

will give you 109181156221

会给你109181156221

but i dont think you would be able to convert it back to IP form.

但我不认为你能将它转换回IP形式。

I would store it with dots.

我会用点存储它。