У меня нет доступа к полному списку подсетей, но тесты по сравнению с опубликованными показали, что это немного быстрее:
сначала «более простая» функция, чтобы увидеть, является ли IP-адресв определенном диапазоне:
Function Find-Subnet ([IPAddress]$SubnetAddress,[byte]$CIDR,[IPAddress]$MatchIP){
[IPAddress]$Mask = [System.Convert]::ToUInt64(('1'*$CIDR).PadRight(32,'0'),2)
return (($SubnetAddress.Address -band $Mask.Address) -eq ($MatchIP.Address -band $Mask.Address))
}
это использует преимущество сдвига битов, объект [System.IPAddress]
может немного подорвать производительность, но все равно кажется намного быстрее, чем связанная функция, игораздо более кратким, вы всегда можете переписать приведение [IPAddress]
в качестве другой двоичной функции, если вам действительно нужна дополнительная производительность, так как в конце мы используем только числовое представление адреса из него.
тогда я смотрючтобы ограничить количество поисков, при поиске по подсетям 2000+ это должно быть значительным увеличением производительности, хотя поиск по немногим в вопросе был лишь небольшим отрицательным.
foreach ($Reg in ('(.*\.).*','(.*\.).*\..*','(.*\.).*\..*\..*')){
$Prefix = $ToMatch -replace $Reg,'$1'
Write-Host "Searching subnets beginning with '$($Prefix)'..." -Fore Yellow
$AllSubnets | ? {$_.Address.StartsWith($Prefix)} | ForEach-Object {
if (Find-Subnet -SubnetAddress $_.Address -CIDR $_.CIDR -MatchIP $ToMatch){
$_ ; break
}
}
}
это циклически повторяетфрагменты регулярных выражений '(.*\.).*'
, '(.*\.).*\..*'
и '(.*\.).*\..*\..*'
, которые при запуске через $Prefix = $ToMatch -replace $Reg,'$1'
приведут к чему-то вроде этого:
'10.11.12.13' -> '(.*\.).*' -> '10.11.12.'
'10.11.12.13' -> '(.*\.).*\..*' -> '10.11.'
'10.11.12.13' -> '(.*\.).*\..*\..*' -> '10.'
мы тогдапросмотрите весь список и вытащите подсети с адресами, начинающимися с префикса, для любой подсети класса A это будет медленнее, чем просто не включая его, для B и C это будет примерно одинаковой или более высокой производительностью, причем B более вероятнобудет медленнее, а вероятность того, что C будет значительно быстрее, будет значительно выше.
ваша текущая функция также не прекращает поиск после того, как обнаружит IP.включив ;break
после возврата соответствующего IP-объекта, мы немедленно возвращаем его и прекращаем поиск, если вы хотите сохранить подсеть в переменной, вы можете сделать $Result = @(foreach ($Reg in ...) { ... })
, чтобы получить ее в $Result
.