Powershell哈希表导出为CSV

Kic*_*all 2 csv powershell hashtable export-to-csv powershell-4.0

我正在尝试创建一个CSV导出文件,其中包含数据电子表格中的所有行,其中显示了搜索电子表格中的ID。

我现在已经设法通过PowerShell创建了搜索元素,但是在将数据导出为CSV格式时遇到了麻烦。

以下是一些示例表,实际数据最多包含8个值(包括ID列),但保证仅前三个值可被填充。

数据表

+------+---------+---------+---------+---------------------+ | ID | Value 1 | Value 2 | Value 3 | Value 4 | +------+---------+---------+---------+---------------------+ | 1234 | London | Serial1 | HP | Laptop User | | 2345 | Moscow | Serial7 | | HR Application | | 1234 | London | Serial9 | | Finance Application | | 3456 | Madrid | Serial4 | HP | Laptop User | +------+---------+---------+---------+---------------------+

搜索电子表格

+------+ | ID | +------+ | 1234 | | 2345 | +------+

所需结果

+------+---------+---------+---------+---------------------+ | ID | Value 1 | Value 2 | Value 3 | Value 4 | +------+---------+---------+---------+---------------------+ | 1234 | London | Serial1 | HP | Laptop User | | 2345 | Moscow | Serial7 | | HR Application | | 1234 | London | Serial9 | | Finance Application | +------+---------+---------+---------+---------------------+

下面是我尝试导出为CSV时删除的当前代码。

$finalValues = @{}

$users = Import-Csv "SEARCH.csv"

$data = Import-Csv "DATA.csv" | Group-Object -property ID -AsHashTable

foreach ($user in $users) 
{
    If ($data.Contains($user.ID))
    {
        #write-output $data[$user.ID].ID
        $finalValues.Add($data[$user.ID].ID, $data[$user.ID])
    }
}
Run Code Online (Sandbox Code Playgroud)

以下两个命令(在脚本的其余部分执行后运行)具有以下输出。

$finalValues.Values

ID      : 1234
Value 1 : London
Value 2 : Serial 1
Value 3 : HP
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Laptop User

ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : HR Application

ID      : 1234
Value 1 : London
Value 2 : Serial9
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Finance Application
Run Code Online (Sandbox Code Playgroud)

$finalValues

{1234, 1234}             {@{ID=1234; Value 1=London; Value 2=Serial1; Value 3=HP; Value 4=; Value 5=; Value 6=; Value 7=Laptop User}, @{ID=1234; Value 1=London; Value 2=Serial 9... ; Value 7 =Finance Application}}

2345                        {@{ID=2345; Value 1=Moscow; Value 2=Serial7; Value 3=; Value 4=; Value 5=; Value 6=; Value 7=HR Application}}           
Run Code Online (Sandbox Code Playgroud)

使用以下命令导出到CSV时,我得到以下结果: $finalValues | export-csv -Path test.csv -NoTypeInformation

+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| IsReadOnly | IsFixedSize | IsSynchronized |                    Keys                    |                    Values                    |   SyncRoot    | Count |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| FALSE      | FALSE       | FALSE          | System.Collections.Hashtable+KeyCollection | System.Collections.Hashtable+ValueCollection | System.Object |    14 |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
Run Code Online (Sandbox Code Playgroud)

使用以下命令导出到CSV时,我得到以下结果:

$finalValues.Values | export-csv -Path test.csv -NoTypeInformation

+-------+------------+-------------+---------------+----------------+
| Count | IsReadOnly | IsFixedSize |   SyncRoot    | IsSynchronized |
+-------+------------+-------------+---------------+----------------+
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     3 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
+-------+------------+-------------+---------------+----------------+
Run Code Online (Sandbox Code Playgroud)

Ben*_*enH 6

这可以通过使用Where-Object过滤器然后使用 导出来简化Export-CSV

$Search = Import-CSV "SEARCH.csv"
Import-CSV "DATA.csv" | Where-Object {$Search.ID -Contains $_.ID} | Export-CSV C:\exampleexportpath.csv -NoTypeInformation
Run Code Online (Sandbox Code Playgroud)


BAC*_*CON 6

@BenH的答案显然是实现此问题的更好方法,但我只是想解释一下原始代码的问题。问题在于,这$dataHashTablestring(用户ID)映射到数组(实际上是a,Collection<PSObject>但出于我们的目的,它的行为相同)。即使在ID '2345'只有一条匹配记录的情况下,$data仍将其存储为具有一个元素的数组:

PS> $data['2345'].GetType().Name
Collection`1
PS> $data['2345'].Count
1
PS> $data['2345']    # Returns the array of values


ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 :
Value 4 : HR Application


PS> $data['2345'][0] # Returns the first element of the array of values


ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 :
Value 4 : HR Application
Run Code Online (Sandbox Code Playgroud)

因此,当这条线执行时...

$finalValues.Add($data[$user.ID].ID, $data[$user.ID])
Run Code Online (Sandbox Code Playgroud)

...您正在将新项添加到$data键和值均为数组的位置。这就是为什么管道输出$finalValues$finalValues.Valuesto的Export-Csv行为就像值是数组的原因。是因为他们是。

为了解决这个问题,访问其中的项目时,$data我们需要一个内部循环来“解包”每个值。另外,我们不能使用HashTablefor,$finalValues因为您使用的ID是键,但是结果中存在重复的IDs('1234')。由于我们需要的是最终要传递给的平坦记录列表Export-Csv,因此我们可以仅使用数组。这是一些修改后的代码...

$finalValues = @() # Cannot be a HashTable because there may be multiple results with the same ID

$users = Import-Csv "SEARCH.csv"

$data = Import-Csv "DATA.csv" | Group-Object -property ID -AsHashTable

foreach ($user in $users)
{
    If ($data.Contains($user.ID))
    {
        # "Unwrap" the array stored at $data[$user.ID]
        foreach ($dataRecord in $data[$user.ID])
        {
            $finalValues += $dataRecord
        }
    }
}

$finalValues | Export-Csv -Path test.csv -NoTypeInformation
Run Code Online (Sandbox Code Playgroud)

...产生这个CSV ...

"ID","Value 1","Value 2","Value 3","Value 4"
"1234","London","Serial1","HP","Laptop User"
"1234","London","Serial9","","Finance Application"
"2345","Moscow","Serial7","","HR Application"
Run Code Online (Sandbox Code Playgroud)