将具有字符串键和 PSObject 值的复杂哈希表导出到 .csv [PowerShell]
Exporting complex Hashtable with string key and PSObject value to .csv [PowerShell]
我有这个名为 $userTable
的用户哈希表,其形式为:.
<key = string, value = PSObject>
对象添加到哈希表如下:
$userTable = @{}
$id="1056456"
$user = New-Object PSObject -Property @{
Name="Test Name"
Email="Test Email"
Systems = New-Object System.Collections.ArrayList
}
$system1 = New-Object PSObject -Property @{
Name="System 1"
Admin=$true
Status="Active"
}
$system2 = New-Object PSObject -Property @{
Name="System 2"
Admin=$false
Status="Inactive"
}
$user.Systems.Add($system1) | Out-Null
$user.Systems.Add($system2) | Out-Null
$userTable.Add($id, $user)
因此对于 $userTable
中的每个条目,都有一个名称、一个电子邮件和一个与该用户关联的系统列表。
我想要做的是将此数据导出到 .csv
,使其采用以下形式:
ID, Name, Email, System Count, System1 Name, System1 Admin, System1 Status, System2 Name, etc..
每个用户可能有超过 2 个系统。
我不知道如何将其导出到 .csv 文件。
如有任何帮助,我们将不胜感激。
我正在考虑使用以下内容:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}} |
Export-Csv -NoTypeInformation -Path C:\Documents\test.csv
但这还不包括系统阵列列表(还)
我不得不同意@MathiasR.Jessen的评论。这在 SO 上经常出现。 CSV 是一种方便的格式,通常是持久存储 and/or 在程序或系统之间中继信息的首选。然而,它是扁平的,因此对于丰富的分层 and/or 复杂对象来说是一个非常糟糕的模拟。
如果对象只有 1 层深,例如,如果 .Systems
本身是一个简单的数组,您可以对该字段进行子分隔。一个很好的例子是 MS Exchange 消息跟踪日志,虽然用“,”分隔,但在“;”上对收件人字段进行了子分隔。然而,它并没有比这更进一步。
简而言之,您为绕过 CSV 格式的限制所做的任何尝试最终都会增加代码的复杂性。您将不得不如此努力地编写 CSV 文件……然后再努力将其重新导入其他地方……
JSON 和 CliXML 是您的替代品。它们都非常适合存储复杂对象的基于文本的表示。此类示例可能类似于:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}},
@{N='Systems'; E={$User.Systems}} |
ConvertTo-Json |
Add-Content -Path "C:\temp\JSONOutput.json"
由于我们没有更多的代码,我不确定 'Systems' 属性 是否被正确填充。但是,您只是将 属性 系统设置为具有 ArrayList 的值,其元素是其他对象。
JSON 显然非常流行,但 CliXML 更适合 PowerShell。 CliXML 替代方案如下所示:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}},
@{N='Systems'; E={$User.Systems}} |
Export-Clixml c:\temp\CliXML_Export.xml
并且,要在其他地方使用数据,分别类似于:
# For JSON:
$SomeVar = (Get-Content "C:\temp\JSONOutput.json") | ConvertFrom-Json
# For CliXml:
$SomeVar = Import-CliXml c:\temp\CliXML_Export.xml
注意:Json 示例中 Get-Content
周围的 (...)
。我相信这在 PowerShell 5.1 中是必需的。尽管我认为这已在 7+ 中得到修复,您可以在其中删除括号。我不确定该限制是否在 6.x.
中
注意:通常在如上所述序列化对象时,方法将被剥离。对于 CliXml,它与 PowerShell 远程处理中用于通过线路序列化对象的格式相同,具有相同的限制。也就是说,出于此处演示的目的,这些格式通常具有足够的保真度以供后续使用。
我有这个名为 $userTable
的用户哈希表,其形式为:.
<key = string, value = PSObject>
对象添加到哈希表如下:
$userTable = @{}
$id="1056456"
$user = New-Object PSObject -Property @{
Name="Test Name"
Email="Test Email"
Systems = New-Object System.Collections.ArrayList
}
$system1 = New-Object PSObject -Property @{
Name="System 1"
Admin=$true
Status="Active"
}
$system2 = New-Object PSObject -Property @{
Name="System 2"
Admin=$false
Status="Inactive"
}
$user.Systems.Add($system1) | Out-Null
$user.Systems.Add($system2) | Out-Null
$userTable.Add($id, $user)
因此对于 $userTable
中的每个条目,都有一个名称、一个电子邮件和一个与该用户关联的系统列表。
我想要做的是将此数据导出到 .csv
,使其采用以下形式:
ID, Name, Email, System Count, System1 Name, System1 Admin, System1 Status, System2 Name, etc..
每个用户可能有超过 2 个系统。
我不知道如何将其导出到 .csv 文件。
如有任何帮助,我们将不胜感激。
我正在考虑使用以下内容:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}} |
Export-Csv -NoTypeInformation -Path C:\Documents\test.csv
但这还不包括系统阵列列表(还)
我不得不同意@MathiasR.Jessen的评论。这在 SO 上经常出现。 CSV 是一种方便的格式,通常是持久存储 and/or 在程序或系统之间中继信息的首选。然而,它是扁平的,因此对于丰富的分层 and/or 复杂对象来说是一个非常糟糕的模拟。
如果对象只有 1 层深,例如,如果 .Systems
本身是一个简单的数组,您可以对该字段进行子分隔。一个很好的例子是 MS Exchange 消息跟踪日志,虽然用“,”分隔,但在“;”上对收件人字段进行了子分隔。然而,它并没有比这更进一步。
简而言之,您为绕过 CSV 格式的限制所做的任何尝试最终都会增加代码的复杂性。您将不得不如此努力地编写 CSV 文件……然后再努力将其重新导入其他地方……
JSON 和 CliXML 是您的替代品。它们都非常适合存储复杂对象的基于文本的表示。此类示例可能类似于:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}},
@{N='Systems'; E={$User.Systems}} |
ConvertTo-Json |
Add-Content -Path "C:\temp\JSONOutput.json"
由于我们没有更多的代码,我不确定 'Systems' 属性 是否被正确填充。但是,您只是将 属性 系统设置为具有 ArrayList 的值,其元素是其他对象。
JSON 显然非常流行,但 CliXML 更适合 PowerShell。 CliXML 替代方案如下所示:
$userTable.GetEnumerator() |
Select-Object -Property @{N='ID'; E={$_.Key}},
@{N='Name'; E={$_.Value.Name}},
@{N='Email'; E={$_.Value.Email}},
@{N='System Count'; E={$_.Value.Systems.Count}},
@{N='Systems'; E={$User.Systems}} |
Export-Clixml c:\temp\CliXML_Export.xml
并且,要在其他地方使用数据,分别类似于:
# For JSON:
$SomeVar = (Get-Content "C:\temp\JSONOutput.json") | ConvertFrom-Json
# For CliXml:
$SomeVar = Import-CliXml c:\temp\CliXML_Export.xml
注意:Json 示例中 Get-Content
周围的 (...)
。我相信这在 PowerShell 5.1 中是必需的。尽管我认为这已在 7+ 中得到修复,您可以在其中删除括号。我不确定该限制是否在 6.x.
注意:通常在如上所述序列化对象时,方法将被剥离。对于 CliXml,它与 PowerShell 远程处理中用于通过线路序列化对象的格式相同,具有相同的限制。也就是说,出于此处演示的目的,这些格式通常具有足够的保真度以供后续使用。