如何从 Foreach 循环中获取添加到集合中的 Powershell 对象的所有值?
How would I get all values of a Powershell Object added to a collection from a Foreach loop?
我有这个函数,它从 $interfaceIPs 获取 InterfaceIndex 并获得匹配的 NetRoute 数据,并将所有这些放在一个集合中。目前在终端上我有 3 个独立的活动 IPv4 地址,但是当我打印集合时,我只得到一个,与来自其各自 NetRoutes 的数据相匹配。
function Get-InterfaceRoutes {
$collection = @()
$interfaceIPs = Get-NetIPConfiguration | Select-Object -Property IPv4Address, InterfaceIndex
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
$collection = [PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
Write-Host "Collection of items: " ($collection | Format-List | Out-String)
}
这是输出:
Collection of items:
Index : 16
Address : {169.254.71.100}
DestinationPrefix : {255.255.255.255/32, 224.0.0.0/4, ff00::/8, fe80::b0b4:b9b0:df22:4764/128...}
NextHop : {0.0.0.0, 0.0.0.0, ::, ::...}
我想让集合显示所有活动的 IP 地址,应该是 3,通过索引与其对应的 NetRoute 数据相匹配。
如果我离题太远并且有更简单的方法,请随时告诉我!
来自 Santiago Squarzon 的有用评论已经解释了基本问题,re-assignment 到变量 $collection
。
虽然在 PowerShell 中,大多数时候您不需要明确地创建和添加到数组,因为 PowerShell 在您捕获函数或函数的输出时自动创建数组声明成一个变量。这也更加 高效 因为每次使用 +=
时 PowerShell 都必须 重新创建 一个数组(数组实际上是 固定大小!)。当 PowerShell 从捕获的输出自动创建一个数组时,它在后台使用 more efficient data structure。
所以我会像这样修改函数:
function Get-InterfaceRoutes {
$interfaceIPs = Get-NetIPConfiguration | Select-Object -Property IPv4Address, InterfaceIndex
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Implicit output!
[PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
}
请注意,我已将 $collection
变量全部删除!
相反,[PSCustomObject]@{}
是函数的隐式 输出。 PowerShell 将它写入 成功流,调用者可以从那里捕获它,或者只是让它通过以在控制台中显示它。
现在,当您真正想要 收集 该函数的输出到一个数组变量中时,您只需 将其赋值 给变量即可。
$routesArray = @(Get-InterfaceRoutes)
"Collection of items:"
$routesArray | Format-List
@()
array subexpression operator 确保您始终创建一个数组,即使该函数仅输出一个对象。
也就是说,有些情况下您实际上想要收集数组变量中的中间输出。假设您想将 foreach
的输出存储在局部变量中以供进一步处理。在这种情况下您仍然不需要显式创建数组,只需从 foreach
语句分配给变量:
# [array] is an alternative to @() for ensuring an array
[array] $collection = Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Implicit output, will be captured and added to $collection
[PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
最后,如果你真的很想显式地创建一个数组(例如,当你需要从一个循环中添加到两个数组时),我建议使用 List
class,这是对于重复添加,比原始数组更有效。此外,它还支持原始数组的所有操作,例如。 G。您可以使用索引运算符 []
来访问其元素。
# Create an instance of List, with elements of type Object.
$collection = [Collections.Generic.List[Object]]::new()
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Add a custom object to the list
$collection.Add( [PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
})
}
我有这个函数,它从 $interfaceIPs 获取 InterfaceIndex 并获得匹配的 NetRoute 数据,并将所有这些放在一个集合中。目前在终端上我有 3 个独立的活动 IPv4 地址,但是当我打印集合时,我只得到一个,与来自其各自 NetRoutes 的数据相匹配。
function Get-InterfaceRoutes {
$collection = @()
$interfaceIPs = Get-NetIPConfiguration | Select-Object -Property IPv4Address, InterfaceIndex
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
$collection = [PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
Write-Host "Collection of items: " ($collection | Format-List | Out-String)
}
这是输出:
Collection of items:
Index : 16
Address : {169.254.71.100}
DestinationPrefix : {255.255.255.255/32, 224.0.0.0/4, ff00::/8, fe80::b0b4:b9b0:df22:4764/128...}
NextHop : {0.0.0.0, 0.0.0.0, ::, ::...}
我想让集合显示所有活动的 IP 地址,应该是 3,通过索引与其对应的 NetRoute 数据相匹配。
如果我离题太远并且有更简单的方法,请随时告诉我!
来自 Santiago Squarzon 的有用评论已经解释了基本问题,re-assignment 到变量 $collection
。
虽然在 PowerShell 中,大多数时候您不需要明确地创建和添加到数组,因为 PowerShell 在您捕获函数或函数的输出时自动创建数组声明成一个变量。这也更加 高效 因为每次使用 +=
时 PowerShell 都必须 重新创建 一个数组(数组实际上是 固定大小!)。当 PowerShell 从捕获的输出自动创建一个数组时,它在后台使用 more efficient data structure。
所以我会像这样修改函数:
function Get-InterfaceRoutes {
$interfaceIPs = Get-NetIPConfiguration | Select-Object -Property IPv4Address, InterfaceIndex
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Implicit output!
[PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
}
请注意,我已将 $collection
变量全部删除!
相反,[PSCustomObject]@{}
是函数的隐式 输出。 PowerShell 将它写入 成功流,调用者可以从那里捕获它,或者只是让它通过以在控制台中显示它。
现在,当您真正想要 收集 该函数的输出到一个数组变量中时,您只需 将其赋值 给变量即可。
$routesArray = @(Get-InterfaceRoutes)
"Collection of items:"
$routesArray | Format-List
@()
array subexpression operator 确保您始终创建一个数组,即使该函数仅输出一个对象。
也就是说,有些情况下您实际上想要收集数组变量中的中间输出。假设您想将 foreach
的输出存储在局部变量中以供进一步处理。在这种情况下您仍然不需要显式创建数组,只需从 foreach
语句分配给变量:
# [array] is an alternative to @() for ensuring an array
[array] $collection = Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Implicit output, will be captured and added to $collection
[PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
}
}
最后,如果你真的很想显式地创建一个数组(例如,当你需要从一个循环中添加到两个数组时),我建议使用 List
class,这是对于重复添加,比原始数组更有效。此外,它还支持原始数组的所有操作,例如。 G。您可以使用索引运算符 []
来访问其元素。
# Create an instance of List, with elements of type Object.
$collection = [Collections.Generic.List[Object]]::new()
Foreach ($interfaceIP in $interfaceIPs) {
$route = Get-NetRoute -InterfaceIndex ($interfaceIP.InterfaceIndex) | Select-Object -Property ifINdex, DestinationPrefix, NextHop, RouteMetric, ifMetric
# Add a custom object to the list
$collection.Add( [PSCustomObject]@{
Index = ($interfaceIp.InterfaceIndex)
Address = ($interfaceIP.IPv4Address)
DestinationPrefix = ($route.DestinationPrefix)
NextHop = ($route.NextHop)
})
}