Powershell - Sort-Objects,IP 地址列表

Powershell - Sort-Objects,IP 地址列表

我有一个 /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() } }

相关内容