2

我被困在一个点上,无法超越它:

我有一个 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函数将它们转换为整数并对其进行排序。但不能再想了。

任何帮助,将不胜感激。

提前致谢 :)

4

4 回答 4

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组

  $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 组是

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
于 2013-04-29T06:13:31.650 回答
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;
}

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

参考:longest_common_substring()

于 2013-04-29T06:37:53.297 回答
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演示>>

于 2013-04-29T12:06:42.863 回答
0
function printCombinedIPs($ip_arr) {
    //$ip_arr = array('192.168.1.5','192.168.1.6');
    $k = NULL;
    $prev = -1;
    foreach ( $ip_arr as $ip ) {
        $octet = explode(".",$ip);
        $fourth = $octet[3];
        $net = $octet[0].".".$octet[1].".".$octet[2];

        if ( $fourth < $prev ) { 
            $prev = -1;
        }

        $end = $fourth;
        if ( $fourth - 1 != $prev ) {
            $start = $fourth;
            $rtn_arr[] = $k;
        }
        
        if ( $start == $end ) 
            $k = $net.".$end";
        else
            $k = $net.".$start-$end";

        $prev = $octet[3];
    }
    $rtn_arr[] = $k;
    array_shift($rtn_arr);
    return implode(", ", $rtn_arr); 
}
于 2022-02-08T20:02:07.197 回答