我有一个 /20 网络,我想知道所有使用的 IP 地址及其属性,如 MAC、名称和描述以及已使用地址之间的所有空闲地址,以便我得到一个长列表,从中我可以查看该地址是否已被使用。幸运的是,我有一个 Server2012,这样我就可以使用 Microsoft 的 CMDLets。我的方法是生成所有可能的地址。最后我想要一个看起来像这样的列表:
IP, Mac, Name, Comment
19.0.0.0, 00:00:11:11:11:01, TestUser_1, This is the 1st Testuser
. (here are some used and some free)
.
19.0.2.45 (this one is free)
.
19.0.6.3 (this one is free, too)
19.0.11.201, 11:22:33:44:55:66, TestUser_N, This is just another comment
示例代码:
$x=0
$y=0
$ipstring = "19.0."
for ($i=$x;$i -le 15; $i++)
{
for ($j=$y;$j -le 255;$j++)
{
$gesIP = $ipstring+"$i"+"."+"$j"
}
}
上述代码创建了 19.0.0.0 至 19.0.15.255 之间的地址
现在我需要获取我使用的地址:
$usedAddresses = Get-DhcpServerv4Reservation -ComputerName $env:computername -ScopeId ((Get-DhcpServerv4Scope -ComputerName $env:computername).IPAddress.IPAddressToString)
我正在考虑按地址空闲的顺序比较这些地址。我不太确定对象列表是否已排序。因此,我尝试使用以下算法对它们进行排序:
$IP_sort = $IPv4_res | Sort-Object {"{0:d3}.{1:d3}.{2:d3}.{3:d3}" -f @([int[]]$_.IPAddress.IPAddressToString.split('.'))}
之后我救了他们
foreach ($ine in $IP_sort)
{
write-output ("{0} {1} {2} {3}" -f ($ine).IPAddress.IPAddressToString, ($ine).ClientId, ($ine).Description, ($ine).Name) | ac EnterPlaceAndTextfileHere
}
现在我得到了 2 个排序列表,我只需要相互比较。第一个列表包含所有地址,第二个列表仅包含已使用的地址。
现在我需要比较这两个列表。我尝试这样做:
if ($ges_IP -eq $IP_sort[$k].IPAddress.IPAddressToString)
{
write-output ("{0} {1} {2} {3}" -f ($IPv4_res[$k]).IPAddress.IPAddressToString, ($IPv4_res[$k]).ClientId, ($IPv4_res[$k]).Name, ($IPv4_res[$k]).Description) | ac EnterPlaceAndTextfileHere
}
else
{
$ges_IP | ac EnterPlaceAndTextfileHere
}
现在我得到了一个大列表,希望它能排序。
但不幸的是,我遇到了一些错误。一些地址与其他属性不匹配,一些地址的顺序不正确。我想知道为什么...我的代码错了吗?是我想得太复杂了,还是 powershell 有时会把这么多地址放在错误的顺序上,而且这种情况有时“就发生了”?
答案1
使用时,Sort-Object
您要对 IP 地址进行排序,因为它是一个字符串。
考虑:
19.0.9.234
19.0.15.5
当示例按字符串升序排序时,19.0.15.5 排在 19.0.9.234 之前。
虽然 15 大于 9,但对字符串进行排序时只考虑位于相同字符串位置的字符,即 1 对 9。
一种解决方案是用 0 填充 IP 八位字节,从而使字符串的长度相同,并使八位字节排列整齐。例如 015、009。
您可以将其Sort-Object
作为计算属性或在存储每个源数据集之前执行此操作。
IE
Sort-Object -Property @{ Expression = { [String]::Join('.', $_.IPAddress.IPAddressToString.Split('.').PadLeft('0', 3)); } }
希望有所帮助。
答案2
我知道这个问题已经解决了,但我只是想为在谷歌上找到此页面的人添加这个选项。
这种方式不使用任何字符串操作:
Get-DhcpServerv4Reservation -ComputerName $env:computername -ScopeId ((Get-DhcpServerv4Scope -ComputerName $env:computername).IPAddress.IPAddressToString) | sort -Property { [Version]$_.IPAddress.IPAddressToString }
或者
$dhcpreservations | sort -Property { [Version]$_.IPAddress.IPAddressToString }
编辑:删除系统因为Ryan Bolgar是正确的
答案3
转换为十六进制字符串适用于 IPv4 和 IPv6 地址。
function ConvertTo-HexString
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[byte[]] $Byte
)
begin
{
[char[]] $digits = @('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
[System.Text.StringBuilder] $hexString = New-Object System.Text.StringBuilder
}
process
{
foreach ($byteValue in $Byte)
{
[void] $hexString.Append($digits[$byteValue -shr 4])
[void] $hexString.Append($digits[$byteValue -band 0x0F])
}
}
end
{
return $hexString.ToString();
}
}
# Because the number of bytes in the different address families is variable,
# sort by the AddressFamily first and then the hexadecimal string.
$ipAddresses | Sort AddressFamily, @{ expression = { ConvertTo-HexString $_.GetAddressBytes() } }
DHCP 预留可按如下方式排序:
Get-DhcpServerv4Reservation -ComputerName $ComputerName -ScopeId $ScopeId | Sort @{ expression = { $_.IPAddress.AddressFamily } }, @{ expression = { ConvertTo-HexString $_.IPAddress.GetAddressBytes() } }