Как объединить IP-адреса из массива и получить диапазоны обратно?

Например, у меня есть массив с этим ips:

$array_ips = array();
$array_ips[] = "32.16.8.133";
$array_ips[] = "32.16.4.247";
$array_ips[] = "32.16.8.184";
$array_ips[] = "32.16.8.127";
$array_ips[] = "32.16.8.134";
$array_ips[] = "32.16.2.154";
$array_ips[] = "32.16.2.153";
$array_ips[] = "32.16.2.150";
sort($array_ips);

Что мне нужно, так это IP-диапазоны.
Для примера мне нужно получить массив с:

32.16.2.150/29
32.16.4.247/32
32.16.8.127/29

Но сейчас я понятия не имею, как это сделать.

Я пробовал вручную что-то вроде этого:

$start = ip2long("32.16.2.150");
$end = ip2long("32.16.2.154");
$range = range($start, $end);
$count_ips = count(array_map('long2ip', $range));
echo $count_ips;
if($count_ips <= 1){
echo '/32';
} else if($count_ips <= 2){
echo '/30';
} else if($count_ips <= 6){
echo '/29';
} else if($count_ips <= 14){
echo '/28';
} else if($count_ips <= 30){
echo '/37';
} else if($count_ips <= 62){
echo '/26';
} else if($count_ips <= 126){
echo '/25';
} else if($count_ips <= 254){
echo '/24';
}

0

Решение

Я нашел себе решение сейчас:

      <?php
$array_ips = array();
$array_ips[] = "32.16.8.133";
$array_ips[] = "32.16.4.247";
$array_ips[] = "32.16.8.184";
$array_ips[] = "32.16.8.127";
$array_ips[] = "32.16.8.134";
$array_ips[] = "32.16.2.154";
$array_ips[] = "32.16.2.153";
$array_ips[] = "32.16.2.150";
sort($array_ips);

function search_array($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && search_array($needle, $element))
return true;
}
return false;
}

$ranges = array();
foreach ($array_ips as $ips) {
$ipparts = explode('.', $ips);
$last = array_pop($ipparts);
$parts = array(implode('.', $ipparts), $last);
$range = $parts[0];
if(!search_array($parts[0], $ranges)) {
$ranges[]['range'] = $parts[0];
}

}

foreach ($ranges as $range) {
$ips_ranges = preg_grep("/".$range['range']."/", $array_ips);
sort($ips_ranges);
$count_ips = count($ips_ranges);
if($count_ips <= 1){
echo $ips_ranges[0].'/32<br>';
} else if($count_ips <= 2){
echo $ips_ranges[0].'/30<br>';
} else if($count_ips <= 6){
echo $ips_ranges[0].'/29<br>';
} else if($count_ips <= 14){
echo $ips_ranges[0].'/28<br>';
} else if($count_ips <= 30){
echo $ips_ranges[0].'/37<br>';
} else if($count_ips <= 62){
echo $ips_ranges[0].'/26<br>';
} else if($count_ips <= 126){
echo $ips_ranges[0].'/25<br>';
} else if($count_ips <= 254){
echo $ips_ranges[0].'/24<br>';
}

}
?>

Выход:

32.16.2.150/29
32.16.4.247/32
32.16.8.127/29
0

Другие решения

Я читал, что нацорт лучше для IP.

http://www.brainbell.com/tutorials/php/Sorting_IP_Addresses_(as_A_Human_Would).htm

Сортировка IP-адресов с помощью sort () на самом деле не работает, поскольку при сортировке в виде строк «100.200.300.400» меньше, чем «50 .60.70.80» (и даже не действительный IP-адрес, но здесь дело не в этом). Кроме того, в строке есть больше, чем просто цифры, поэтому числовая сортировка не работает.

Это решение предполагает, что ваши диапазоны имеют 3 фиксированных октета. Это не будет работать для 192.168.0.0/16.

<?php
$array_ips = array();
$array_ips[] = "32.16.8.133";
$array_ips[] = "32.16.4.247";
$array_ips[] = "32.16.8.184";
$array_ips[] = "32.16.8.127";
$array_ips[] = "32.16.8.134";
$array_ips[] = "32.16.2.154";
$array_ips[] = "32.16.2.153";
$array_ips[] = "32.16.2.150";

natsort($array_ips);

$ranges = array();

foreach($array_ips as $ip)
{
$pieces = explode('.', $ip);
$current_range = $pieces[0] . '.' . $pieces[1] . '.' .$pieces[2];
if(!isset($ranges[$current_range])) {
$ranges[$current_range] = 1;
} else {
$ranges[$current_range] ++;
}

}

foreach($ranges as $range => $count){
echo $range .": " . $count . "\n";
}
?>

Выход

32.16.2: 3
32.16.4: 1
32.16.8: 4
0

По вопросам рекламы [email protected]