使用PHP合并IP范围

时间:2013-04-29 06:03:30

标签: php sorting ip

我陷入困境,无法超越它:

我有一个Ip范围列表,我需要将它们合并为一个范围。例如

  

192.168.1.1

     

192.168.1.2

     

192.168.1.3

     

192.168.1.5

     

192.168.1.6

我需要将它们归入IP范围。对于这种情况,它将是192.168.1.1 - 192.168.1.3192.168.1.5 - 192.168.1.6

我正在考虑使用ip2long函数将它们转换为整数并对其进行排序。但除此之外无法思考。

任何帮助将不胜感激。

提前谢谢:)

3 个答案:

答案 0 :(得分:3)

您可以使用ip2long http://php.net/manual/en/function.ip2long.php将包含(IPv4)互联网协议虚线地址的字符串转换为适当的地址,您可以使用此范围

echo ip2long('192.168.1.1');//-1062731519

echo ip2long('192.168.1.6');//-1062731514

使用此功能,您可以检查用户的IP范围,...是否有效,或者......

例如,如果用户ip在192.168.1.1-192.168.1.6范围内echo 'hello';

//http://www.php.net/manual/en/function.ip2long.php#81030
function in_ip_range($ip_one, $ip_two=false){ 
  if($ip_two===false){ 
    if($ip_one==$_SERVER['REMOTE_ADDR']){ 
        $ip=true; 
    }else{ 
        $ip=false; 
    } 
  }else{ 
    if(ip2long($ip_one)<=ip2long($_SERVER['REMOTE_ADDR']) && ip2long($ip_two)>=ip2long($_SERVER['REMOTE_ADDR'])){ 
        $ip=true; 
    }else{ 
        $ip=false; 
    } 
  } 
  return $ip; 
 } 
 //usage 
 if(in_ip_range('192.168.1.1','192.168.1.6')){
    echo 'hello';
 }

ip group

  $list=array(
   '192.168.1.1',
   '192.168.1.2',

   '192.168.1.3',

   '192.168.1.5',

   '192.168.1.6',
   '192.168.1.6',
   '192.168.1.9'
 );
 $Grouplist='';
 foreach($list as $ip){ 
       $ip2long=ip2long($ip);
       if(is_array($Grouplist)){
            $is_group=false;
            foreach($Grouplist as $Key=>$Range){
                 $Range=explode("/",$Range);
                 if(($Range[0]-1)<$ip2long and $ip2long<($Range[1]+1)){
                       $is_group=true;
                       continue;
                 }elseif(($Range[0]-1)==$ip2long){
                       $Grouplist[$Key]=$ip2long.'/'.$Range[1];
                       $is_group=true;
                 }elseif(($Range[1]+1)==$ip2long){
                      $Grouplist[$Key]=$Range[0].'/'.$ip2long;
                      $is_group=true;
                 }
            }
            if(!$is_group)
            {
                  $Grouplist[]=($ip2long).'/'.($ip2long);
            }
       }else{
             $Grouplist[]=($ip2long).'/'.($ip2long);
       }
 }
     print_r($Grouplist); 

输出:

 Array
(
   [0] => -1062731519/-1062731517  
   [1] => -1062731515/-1062731514
   [2] => -1062731511/-1062731511
)

如果转换为ip group是

foreach($Grouplist as $Val){
     $Range=explode("/",$Val);
     echo long2ip($Range[0])."/".long2ip($Range[1])."\n";
}

输出

192.168.1.1/192.168.1.3
192.168.1.5/192.168.1.6
192.168.1.9/192.168.1.9

答案 1 :(得分:2)

以下是我的回答:

$ip_list = array('192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.5', '192.168.1.6');
$ip_long_list = array();
foreach($ip_list as $ip) {
  $ip_long_list[] = ip2long($ip);
}
unset($ip_list); // no longer in use 
sort($ip_long_list); // sort it

$result = array();
$cnt_group = 0;
for($i = 0; $i < count($ip_long_list)-1; $i++) {
  if($i == 0) {
    $result[$cnt_group] = array($ip_long_list[0]); // initialize 1st group
    continue;
  }
  if(abs($ip_long_list[$i] - $ip_long_list[$i+1]) == 1) {
    // they are in series, group it.
    $tmp_array = $result[$cnt_group]; // get back the array
    $tmp_array[] = $ip_long_list[$i]; // push item into array
    $result[$cnt_group] = $tmp_array;
    unset($tmp_array); // remove to save memory
  } else {
    // they are separate. next group.
    $cnt_group++;
    $result[$cnt_group] = array($ip_long_list[1]);
  }
}

完成上述所有操作后,请从Long转换回IP。

foreach($result as $ip_long_group) {
  $first_ip = long2ip($ip_long_group[0]);
  $last_ip = long2ip($ip_long_group[count($ip_long_group)-1];

  $common_parts = longest_common_substring(array($first_ip, $last_ip));

  echo $common_parts . str_replace($common_parts, '', $first_ip) . '-' . str_replace($common_parts, '', $last_ip) . PHP_EOL;
}

注意:我使用了第三方函数(参考文献中列出)来获取2个字符串的公共部分。

参考:longest_common_substring()

答案 2 :(得分:1)

获取范围的手动方法(不使用ip2long):

<?php  
 $ip_addressess=array(
   '192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.5', '192.168.1.6', '192.168.1.7', '192.168.1.9', '192.168.1.10',   '192.168.1.11', '192.168.1.15', '192.168.1.16', '192.168.1.17');

foreach($ip_addressess as $ip_address){
    $break_ip[] = explode('.', $ip_address); //break ip address
 }
foreach($break_ip as $break){
    $numbers[] = $break[3]; //get last number of ip address
}
$commaList_ipaddress = implode(',', $numbers); //generate comma separated list of last digits of ip address
$missing = array();
$a =0 ;
for ($i = 1; $i <= max($numbers); $i++) {
    if (!in_array($i, $numbers))
    {       
        $missing[] = $i;
    $a++;

    } else{
    $new_ip_ranges[$a][] = $i;    
    }

}
$new_ip_ranges = array_values($new_ip_ranges); //rearrange the array
foreach($new_ip_ranges as $new_range){
    $min = min($new_range);
    $max  = max($new_range);    
    $min_range = $break_ip[0][0].'.'.$break_ip[0][1].'.'.$break_ip[0][2].'.'.$min;
    $max_range = $break_ip[0][0].'.'.$break_ip[0][1].'.'.$break_ip[0][2].'.'.$max;       
    $range[] = $min_range .'-'.$max_range; 

}
echo '<pre>';
print_r($range);


?>

输出:

Array
(
    [0] => 192.168.2.1-192.168.2.3
    [1] => 192.168.2.5-192.168.2.7
    [2] => 192.168.2.9-192.168.2.11
    [3] => 192.168.2.15-192.168.2.17
)

CodeFiddle>>

演示