如何导出具有不同数量属性的对象?

时间:2013-01-09 03:42:48

标签: powershell

警告 - 我过去曾问similar question,但情况略有不同。

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

最初,如果您要导出-csv这些对象的数组,那么标头将建立在第一个对象上(也就是说,您只能得到ServerName,IP1,IP2,NIC1和NIC2),这意味着第二个对象丢失任何后续IP(例如IP3和IP4)。为了解决这个问题,在导出之前我根据IP属性的数量排序 - tada - 第一个对象现在拥有数组中最多的IP,因此没有后续对象IP丢失。

缺点是当你有第二个不同的属性 - 例如NIC。基于IP完成排序后,我们将标题为ServerName,IP1 - IP4和NIC1。这意味着NIC2的后续对象属性将丢失。

是否有可扩展的方法来确保在导出此类对象时不会丢失数据?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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