Например, у меня есть массив с этим 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';
}
Я нашел себе решение сейчас:
<?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
Я читал, что нацорт лучше для 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