我正在 PowerShell 中编写一个脚本,用于从 Active Directory 导出所有安全组及其成员。现在我想格式化 CSV 文件的输出。
代码:
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=SERVICES,DC=XXXXXX,DC=XXXXX"
$Table = @()
$Record = @{
"Group Name" = ""
"Name" = ""
"Username" = ""
}
Foreach($G In $Groups)
{
$Arrayofmembers = Get-ADGroupMember -identity $G -recursive | select name,samaccountname
Foreach ($Member in $Arrayofmembers)
{
$Record."Group Name" = $G.Name
$Record."Name" = $Member.name
$Record."UserName" = $Member.samaccountname
$objRecord = New-Object PSObject -property $Record
$Table += $objrecord
}
}
$Table | export-csv "C:\temp\SecurityGroups.csv" -NoTypeInformation
结果:
"Username","Name","Group Name"
"aman","Ani Manoukian","Commercial"
"adan","Aurelia Danneels","Commercial"
"kdeb","Kathleen De Backer","Commercial"
"TVGR","Thijs Van Grimbergen","Commercial"
"SVDE","Sofie Van den Eynde","Commercial"
现在我希望按以下顺序格式化输出:
“组名”、“名称”、“用户名”
而不是:"用户名","姓名","组名"
gvee's helpful answer是一种实用解决方案,可确保列以所需的顺序出现,因为您将属性名称传递给 Select-Object
是将属性添加到结果 [pscustomobject]
中的顺序实例。
然而,它效率低下,因为在 $Record
时可以确保所需的列顺序已定义,不需要有效复制结果对象的额外管道阶段:
定义 $Record
作为有序哈希表如下(需要PSv3+):
$Record = [ordered] @{
"Group Name" = ""
"Name" = ""
"Username" = ""
}
这保证了 [pscustomobject]
稍后由 New-Object PSObject -property $Record
创建的实例调用包含的属性与 $Record
中定义的键的顺序相同。 .
两旁:
-
New-Object PSObject -property $Record
可以简化为 [pscustomobject] $Record
- 使用
[System.Collections.ArrayList]
可以更有效地以增量方式构建大型数组。使用 .Add()
添加元素的实例而不是使用 PowerShell 的内置数组和 +=
,它每次都会创建一个数组的副本。更好的是让 PowerShell 为您创建数组,只需捕获 foreach
的输出即可。在变量中循环($Table = foreach ...
- 见 this answer)
补充资料:
问题的根源在于常规哈希表([hashtable]
实例)以有效的不可预测顺序枚举它们的键(顺序是实现细节,不保证),当您创建 [pscustomobject]
从哈希表中,不可预测的键顺序反射(reflect)在结果对象属性的顺序中。
相比之下,在 PSv3+ 中,您可以通过放置 [ordered]
来创建一个有序哈希表关键字 在哈希表文字之前,这会导致 [System.Collections.Specialized.OrderedDictionary]
实例,其键是根据它们的添加顺序添加。
创建 [pscustomobject]
然后,来自有序哈希表的实例将该键排序保留在结果对象的属性中。
请注意,PowerShell v3+ 提供了一个方便的快捷方式来创建 [pscustomobject]
使用 cast 的哈希表中的实例;例如:
PS> [pscustomobject] @{ a = 1; b = 2; c = 3 } # key order is PRESERVED
a b c
- - -
1 2 3
注意键定义顺序是如何保留的,即使[ordered]
未指定。
换句话说:当您将哈希表文字直接转换为[pscustomobject]
时, [ordered]
是隐含的,所以上面等价于:
[pscustomobject] [ordered] @{ a = 1; b = 2; c = 3 } # [ordered] is optional
警告:此隐式排序仅适用于散列表文字直接转换为[pscustomboject]
的情况,因此键/属性顺序不保留在以下变体中:
New-Object PSCustomObject -Property @{ a = 1; b = 2; c = 3 } # !! order NOT preserved
$ht = @{ a = 1; b = 2; c = 3 }; [pscustomobject] $ht # !! order NOT preserved
[pscustomobject] (@{ a = 1; b = 2; c = 3 }) # !! order NOT preserved, due to (...)
因此,当不将哈希表文字直接转换为[pscustomobject]
时, 用 [ordered]
定义它明确的。
我是一名优秀的程序员,十分优秀!