0

警告 - 我过去曾问过类似的问题,但这略有不同。

tl;博士; 我想导出具有不同数量属性的对象。例如; 对象 1 可能有 3 个 IP 地址和 2 个 NIC,但对象 2 有 7 个 IP 地址和 4 个 NIC(但不限于此数量 - 它可能是 N 个属性)。

我可以愉快地捕获和构建包含我需要的所有信息的对象。如果我只是将数组输出到控制台,每个对象都会显示其所有属性。如果我想 out-file 或 export-csv 我开始遇到标题周围的问题。

以前JPBlanc建议根据属性的数量对对象进行排序 - 即,具有最多属性的对象将排在第一位,因此将输出最多属性的标题。

假设我已经构建了一个服务器对象,该对象具有基于 IP 地址和 NIC 卡的不同属性。例如;

ServerName: Mordor
IP1: 10.0.0.1
IP2: 10.0.0.2
NIC1: VMXNET
NIC2: Broadcom

ServerName: Rivendell
IP1: 10.1.1.1
IP2: 10.1.1.2
IP3: 10.1.1.3
IP4: 10.1.1.4
NIC1: VMXNET

最初,如果您要导出这些对象的数组,则标头将建立在第一个对象(也就是,您只会获得 ServerName、IP1、IP2、NIC1 和 NIC2)的基础上,这意味着对于第二个对象,您将丢失任何后续IP(例如 IP3 和 IP4)。为了纠正这个问题,在导出之前,我根据 IP 属性的数量进行排序 - tada - 第一个对象现在在数组中拥有最多的 IP,因此后续对象的 IP 都不会丢失。

不利的一面是当您拥有第二个可变属性时 - 例如 NIC。一旦我的排序基于 IP 完成,我们就会有标题 ServerName、IP1 - IP4 和 NIC1。这意味着 NIC2 的后续对象属性丢失。

有没有一种可扩展的方式来确保在导出这样的对象时不会丢失数据?

4

3 回答 3

0

尝试:

$o1 = New-Object psobject -Property @{
ServerName="Mordor"
IP1="10.0.0.1"
IP2="10.0.0.2"
NIC1="VMXNET"
NIC2="Broadcom"
}

$o2 = New-Object psobject -Property @{
ServerName="Rivendell"
IP1="10.1.1.1"
IP2="10.1.1.2"
IP3="10.1.1.3"
IP4="10.1.1.4"
NIC1="VMXNET"
}

$arr = @()
$arr += $o1
$arr += $o2

#Creating output
$prop = $arr | % { Get-Member -InputObject $_ -MemberType NoteProperty | Select -ExpandProperty Name } | Select -Unique | Sort-Object
$headers = @("ServerName")
$headers += $prop -notlike "ServerName"

$arr | ft -Property $headers    

输出:

ServerName IP1      IP2      IP3      IP4      NIC1   NIC2    
---------- ---      ---      ---      ---      ----   ----    
Mordor     10.0.0.1 10.0.0.2                   VMXNET Broadcom
Rivendell  10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4 VMXNET         

如果您知道类型(NICS、IPS ..),但不知道计数(例如多少 NICS),您可以尝试:

#Creating output
$headers = $arr | % { Get-Member -InputObject $_ -MemberType NoteProperty | Select -ExpandProperty Name } | Select -Unique
$ipcount = ($headers -like "IP*").Count
$niccount = ($headers -like "NIC*").Count

$format = @("ServerName")
for ($i = 1; $i -le $ipcount; $i++) { $format += "IP$i" }
for ($i = 1; $i -le $niccount; $i++) { $format += "NIC$i" }

$arr | ft -Property $format
于 2013-01-09T09:30:35.510 回答
0

如何获取所有唯一属性标题的列表,然后对所有对象进行选择?当您对不存在的属性的对象进行选择时,它将创建一个空白。

$allHeaders = $arrayOfObjects | % { Get-Member -inputobject $_ -membertype noteproperty | Select -expand Name } | Select -unique
$arrayOfObjects | Select $allHeaders

当然,您正在遍历任何对象以获取标题,因此对于大量对象可能需要一段时间。

于 2013-01-09T16:32:54.317 回答
0

这是我的解决方案尝试。我现在很累,所以希望这是有道理的。基本上,我正在计算最大数量的 NIC 和 IP 注释属性,创建一个具有这些属性数量的占位符对象,将其添加为 CSV 中的第一项,然后将其从 CSV 中删除。

# Create example objects
$o1 = New-Object psobject -Property @{
  ServerName="Mordor"
  IP1="10.0.0.1"
  IP2="10.0.0.2"
  NIC1="VMXNET"
  NIC2="Broadcom"
}

$o2 = New-Object psobject -Property @{
  ServerName="Rivendell"
  IP1="10.1.1.1"
  IP2="10.1.1.2"
  IP3="10.1.1.3"
  IP4="10.1.1.4"
  NIC1="VMXNET"
}

# Add to an array
$servers = @($o1, $o2)

# Calculate how many IP and NIC properties there are
$IPColSize = ($servers | Select IP* | %{($_ | gm -MemberType NoteProperty).Count} | Sort-Object -Descending)[0]
$NICColSize = ($servers | Select NIC* | %{($_ | gm -MemberType NoteProperty).Count} | Sort-Object -Descending)[0]

# Build a place holder object that will contain enough properties to cover all of the objects in the array.
$cmd = '$placeholder = "" | Select ServerName, {0}, {1}' -f (@(1..$IPColSize | %{"IP$_"}) -join ", "), (@(1..$NICColSize | %{"NIC$_"}) -join ", ")
Invoke-Expression $cmd

# Convert to CSV and remove the placeholder
$csv = $placeholder,$servers | %{$_ | Select *} | ConvertTo-Csv -NoTypeInformation
$csv | Select -First 1 -Last ($csv.Count-2) | ConvertFrom-Csv | Export-Csv Solution.csv -NoTypeInformation
于 2013-01-10T04:20:39.327 回答