处理异构阵列(成员)



让我们创建书籍

$a = New-Object –TypeName PSObject
$a | Add-Member –MemberType NoteProperty –Name Title –Value "Journey to the West" 
$a | Add-Member –MemberType NoteProperty –Name Price –Value 12
$b = New-Object –TypeName PSObject
$b | Add-Member –MemberType NoteProperty –Name Title –Value "Faust" 
$b | Add-Member –MemberType NoteProperty –Name Author –Value "Goethe"
$array1 = $a,$b
$array2 = $b,$a

现在让我们显示这两个数组

PS D:DeveloppementPowershell> $array1
Title               Price
-----               -----
Journey to the West    12
Faust                    
PS D:DeveloppementPowershell> $array2
Title               Author
-----               ------
Faust               Goethe
Journey to the West
因此,据

我了解,这基本上意味着powershell认为数组的属性是其第一个元素的属性(事实上,这甚至不是真的,因为如果第一个元素$null则下一个元素将被考虑)。现在这也意味着:

  • 如果在数组上调用Get-Member,则只会获取第一个元素的成员
  • 如果对数组调用Convert-ToCvs,则只会导出第一个元素定义的属性的属性值

我几乎不明白这背后的合理性,这种行为让我在 powershell 中使用异构数组感到非常痛苦。

我想从各种外部来源导入数据,处理它们,然后将它们导出到 cvs 文件。项目是相似的,但其中大多数都不可预测地错过了一些属性。有没有明显的方法可以在Powershell中处理这个问题而无需重新编程轮子?

这是

必须的方式,因为PowerShell使用管道。当你运行 ex. $array1 | Export-CSV ....,PowerShell在第一个对象到达时就开始写入CSV文件。此时,它需要知道标头的外观,因为这是csv文件中的第一行。因此,PowerShell 必须假定第一个对象的类/属性表示管道中的所有剩余对象。这同样适用于需要在输出任何对象之前设置样式/视图的Format-Table和类似命令。

通常的解决方法是使用 Select-Object 手动指定标头。它将把所有缺少的属性添加到值为 $null 的所有对象中。这样,所有对象都发送到 ex。 Export-CSV将定义所有相同的属性。

要获取标头,您需要从数组中的所有对象接收所有唯一的属性名称。

$array1 |
ForEach-Object { $_.PSObject.Properties} |
Select-Object -ExpandProperty Name -Unique
Title
Price
Author

然后,您可以在将对象发送到 Ex 之前使用 Select-Object -Properties Title,Price,Author 将其指定为标头Export-CSV

$a = New-Object –TypeName PSObject
$a | Add-Member –MemberType NoteProperty –Name Title –Value "Journey to the West" 
$a | Add-Member –MemberType NoteProperty –Name Price –Value 12
$b = New-Object –TypeName PSObject
$b | Add-Member –MemberType NoteProperty –Name Title –Value "Faust" 
$b | Add-Member –MemberType NoteProperty –Name Author –Value "Goethe"
$array = $a,$b
$AllProperties = $array |
ForEach-Object { $_.PSObject.Properties} |
Select-Object -ExpandProperty Name -Unique
$array | Select-Object -Property $AllProperties | Export-CSV -Path "mycsv.out" -NoTypeInformation

这将创建此 CSV 文件:

"Title","Price","Author"
"Journey to the West","12",
"Faust",,"Goethe"

如果你有多个数组,你可以像这样组合它们$array = $array1 + $array2

最新更新