在PowerShell中导出为CSV时,如何指定列顺序?

dkqlctbz  于 2023-06-19  发布在  Shell
关注(0)|答案(2)|浏览(190)

我正在用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"

现在我希望输出按以下顺序格式化:

"Group Name","Name","Username"
别名:"Username","Name","Group Name"

67up9zun

67up9zun1#

gvee's helpful answer是一个实用的解决方案,它确保列以所需的顺序出现,因为将属性名传递给Select-Object的顺序就是将属性添加到最终[pscustomobject]示例的顺序。
然而,它是低效的,因为$Record被 * 定义时可以确保所需的列顺序,而不需要额外的流水线阶段来有效地复制结果对象:
$Record定义为
有序 * 哈希表,如下所示(需要PSv 3 +;省略了可选引用;使用单引号):

$Record = [ordered] @{
    'Group Name' = ''
    Name = ''
    Username = ''
}

这保证了New-Object PSObject -property $Record调用稍后创建的[pscustomobject]示例包含的属性的顺序与$Record中定义的键的顺序相同。
两句话:

  • New-Object PSObject -property $Record可以简化为[pscustomobject] $Record(见下文)
  • 使用.Add()[System.Collections.ArrayList]示例添加元素,而不是使用+=使用PowerShell的内置数组(每次都创建一个数组副本),可以更有效地增量构建大型数组。更好的方法是让PowerShell为您创建数组,只需在变量中捕获foreach循环的输出($Table = foreach ...-参见this answer

补充信息:

问题的根源在于常规哈希表([hashtable]示例)以有效的 * 不可预测 * 顺序(顺序是实现细节,* 不保证 )枚举它们的键,并且当您从哈希表创建[pscustomobject]时,这种不可预测的键顺序反映在结果对象属性的顺序中。
相比之下,在PSv 3 +中,您可以通过将[ordered]关键字放在哈希表文字之前来创建 * 有序 * 哈希表,这将导致
*[System.Collections.Specialized.OrderedDictionary]示例的键根据它们 * 添加*的顺序进行排序。
从一个有序的哈希表创建一个[pscustomobject]示例,然后在结果对象的属性中保留键的顺序。
请注意,PowerShell v3+提供了一个
方便的快捷方式,用于使用 cast**从哈希表创建[pscustomobject]示例;例如:

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]定义它。

a11xaf1n

a11xaf1n2#

这应该可以。。

$Table |
  Select-Object "Group Name", "Name", "Username" |
  Export-Csv "C:\temp\SecurityGroups.csv" -NoTypeInformation

相关问题