【问题标题】:How can I specify the column ordering when exporting to CSV in PowerShell?在 PowerShell 中导出为 CSV 时如何指定列顺序?
【发布时间】:2017-06-24 18:13:18
【问题描述】:

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

【问题讨论】:

    标签: powershell csv formatting export-to-csv


    【解决方案1】:

    这应该可以...

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

    【讨论】:

    • 当您不控制集合的创建(或不想)时,此答案也适用
    【解决方案2】:

    gvee's helpful answer 是一种实用 解决方案,可确保列按所需顺序显示,因为将属性名称传递给Select-Object 的顺序就是添加属性的顺序到生成的[pscustomobject] 实例。

    然而,它效率低下,因为$Record定义时可以确保所需的列顺序,而不需要一个额外的管道阶段,有效地复制结果对象:

    $Record 定义为有序哈希表,如下所示(需要PSv3+):

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

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

    两旁:

    • New-Object PSObject -property $Record 可以简化为 [pscustomobject] $Record
    • 使用[System.Collections.ArrayList] 向其中添加元素的.Add() 实例可以更有效地处理增量构建大型数组,而不是使用带有+= 的PowerShell 内置数组,后者每次都会创建数组的副本.更好的是让 PowerShell 为您创建数组,只需在变量中捕获 foreach 循环的输出($Table = foreach ... - 请参阅 this answer

    补充资料:

    问题的根源在于常规哈希表([hashtable] 实例)以有效的不可预测顺序枚举其键(该顺序是实现细节,不保证),并且当您从哈希表创建[pscustomobject] 时,不可预测的键顺序会反映在结果对象属性的顺序中。

    相比之下,在 PSv3+ 中,您可以通过在前面放置 [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] 显式定义它。

    【讨论】:

      猜你喜欢
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 2018-09-15
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      相关资源
      最近更新 更多