[英]Powershell Hashtable Export to CSV
我正在嘗試創建一個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])
}
}
以下兩個命令(在執行其余腳本后運行)具有以下輸出。
$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
$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}}
使用以下命令導出到CSV時,我得到以下結果: $finalValues | export-csv -Path test.csv -NoTypeInformation
$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 |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
使用以下命令導出到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 |
+-------+------------+-------------+---------------+----------------+
@ BenH的答案顯然是實現這一目標的更好方法,但我只想解釋原始代碼的問題。 問題是$data
是一個HashTable
,它將一個string
(用戶ID
)映射到一個數組 (實際上它是一個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
因此,當這一行執行時......
$finalValues.Add($data[$user.ID].ID, $data[$user.ID])
...您正在向$data
添加一個新項目,其中鍵和值都是數組。 這就是為什么輸出管道$finalValues
或$finalValues.Values
到Export-Csv
行為就像值是數組一樣; 這是因為他們是。
要解決這個問題,當訪問$data
項目時,我們需要一個內部循環來“解包”每個值。 此外,我們不能將$finalValues
HashTable
用於$finalValues
因為您使用ID
作為鍵,但結果中有重復的ID
( '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
...產生這個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"
這可以通過使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.