如何在foreach循环中对导入的csv中的唯一值进行分组



我有一个包含以下内容的txt文件:

#test.txt

'ALDHT21;MIMO;1111;BOK;Tree'
'ALDHT21;MIMO;1211;BOK;Tree'
'PRGHT21;AIMO;1351;STE;Water'
'PRGHT21;AIMO;8888;FRA;Stone'
'ABCDT22;DIDO;8888;STE;Stone'
'PRA2HT21;ADDO;8888;STE;Stone'
';ADDO;1317;STE;Stone'

为了更容易解释,让我们给出上面的内容标题:''集团;密码身份证件签名类型">

在Powershell的帮助下,我试图创建每个唯一的";签名";以从行返回具有唯一数据的两个变量;签名";存在于中,然后与一些分隔符混在一起。

根据文件内容,以下是预期结果:

第一个循环:

$Signature = "BOK" 
$Groups = "Tree:ALDHT21"
$Codes = "Tree:MIMO"

下一个循环:

$Signature = "FRA"
$Groups = "Stone:PRGHT21"
$Codes = "Stone:AIMO"

最后一个循环:

$Signature = "STE"
$Groups = "Stone:PRA2HT21,Stone:ABCDT22,Water:PRGHT21"
$Codes = "Stone:ADDO,Stone:DIDO,Water:AIMO"

请注意,最后一个循环应该跳过文件中的最后一个条目,因为它包含一个空的Group。

我的尝试没有达到目标,我正在努力寻找一个好的方法来实现这一点:

$file = "C:temptest.txt"
$uniqueSigs = (gc $file) -replace "'$|^'" | ConvertFrom-Csv -Delimiter ';' -Header Group,Code,ID,Signature,Type | group Signature
foreach ($sigs in $uniqueSigs) {
$Groups = ""
foreach ($Group in $sigs.Group) {
$Groups += "$($Group.Type):$($Group.Group),"
}
$Groups = $Groups -replace ",$" 
[PSCustomObject] @{
Signatur = $sigs.Name
Groups = $Groups
}
$Codes = ""
foreach ($Group in $sigs.Group) {
$Codes += "$($Group.Type):$($Group.Code),"
}
$Codes = $Codes -replace ",$" 
[PSCustomObject] @{
Signatur = $sigs.Name
Codes = $Codes
}
$Signature = $sigs.Name
If ($Group.Group){
write-host "$Signature "-" $Groups "-" $Codes "
}
}

我的错误尝试的结果:

BOK  - Tree:ALDHT21,Tree:ALDHT21 - Tree:MIMO,Tree:MIMO 
FRA  - Stone:PRGHT21 - Stone:AIMO

感谢您的帮助。:(

您的变量命名有些混乱;以下简化的解决方案使用较少的变量,可能会产生所需的结果:

$file = "test.txt"
(Get-Content $file) -replace "'$|^'" | ConvertFrom-Csv -Delimiter ';' -Header Group,Code,ID,Signature,Type |
Group-Object Signature |
ForEach-Object {
# Create and output an object with group information.
# Skip empty .Group properties among the group's member objects.
# Get the concatenation of all .Group and .Code column
# values each, skipping empty groups and eliminating duplicates.
$groups = (
$_.Group.ForEach({ if ($_.Group) { "$($_.Type):$($_.Group)" } }) |
Select-Object -Unique
) -join ","
$codes = (
$_.Group.ForEach({ "$($_.Type):$($_.Code)" }) |
Select-Object -Unique
) -join ","
# Create and output an object comprising the signature
# and the concatenated groups and codes.
[PSCustomObject] @{
Signature = $_.Name
Groups = $groups
Codes = $codes
}
# Note: This is just *for-display* output.
# Don't use Write-Host to output *data*.
Write-Host ($_.Name, $groups, $codes -join ' - ')
}

输出:

BOK - Tree:ALDHT21 - Tree:MIMO
FRA - Stone:PRGHT21 - Stone:AIMO
STE - Water:PRGHT21,Stone:ABCDT22,Stone:PRA2HT21 - Water:AIMO,Stone:DIDO,Stone:ADDO
Signature Groups                                     Codes
--------- ------                                     -----
BOK       Tree:ALDHT21                               Tree:MIMO
FRA       Stone:PRGHT21                              Stone:AIMO
STE       Water:PRGHT21,Stone:ABCDT22,Stone:PRA2HT21 Water:AIMO,Stone:DIDO,Stone:ADDO

请注意,显示Write-Host出人意料地先于[pscustomobject]实例的默认输出格式,这是由于本答案中解释的隐式应用Format-Table格式的异步行为。