【问题标题】:Powershell: Merge selective columns in 2 CSV filePowershell:合并 2 个 CSV 文件中的选择性列
【发布时间】:2013-07-14 21:11:54
【问题描述】:

由于突然需要编写脚本,将 2 个 csv 文件与至少有 1 个公共列的行和列结合起来,我求助于 powershell。我是 Powershell 的菜鸟。谁能建议如何从两个文件中读取,将一行与一个公共列进行比较和组合,最后输出到另一个文件?

CSV 文件 1

Hosts  ABC  DEF
=====  ===  ===
SVR01   10  100
SRV02   22   99

CSV 文件 2

Hosts  UVW   XYZ
=====  ===   ===
SVR01   13  10.5
SRV02   19   8.9

预期输出

Hosts  DEF  UVW   XYZ
=====  ===  ===   ===
SVR01  100   13  10.5
SRV02   99   19   8.9

希望寻求一些指导。

谢谢。

【问题讨论】:

  • 公共列在两个文件中的值是否相同?这些价值观是独一无二的吗?你知道栏目标题吗?到目前为止,您尝试过什么?
  • 这些是 CSV 中的标题:"Object ID","Volume","Aggregate","Storage Server","Used","Total","Used (%)" where "Object ID”是唯一的列。我已经在下面尝试了 gpduck 编写的脚本,但是根据我对 gpduck 的回复,我遇到了一些问题。
  • 两个文件的行数是否相同且对象 ID 相同?
  • 您可以为此使用PowerShell Gallery 中的[Join-Object] cmdletImport-CSV .\file1.csv | Join (Import-CSV .\file2.csv) Hosts | Export-CSV .\OutFile.csv

标签: file powershell join csv


【解决方案1】:

如果文件不会太大,我会使用公共列值作为键将一个文件加载到哈希表中,然后遍历第二个文件并使用键值查找要从第一个合并的列文件。如果第一个文件很大(大小取决于你有多少 RAM),你只需要注意占用过多的 RAM,因为它的全部内容将被加载到内存中。

#Make an empty hash table for the first file

$File1Values = @{}


#Import the first file and save the rows in the hash table indexed on "KeyColumn"

Import-Csv -Path c:\file1.csv | ForEach-Object {
  $File1Values.Add($_.KeyColumn, $_)
}


#Import the second file, using Select-Object to select all the values from file2,
#  and adding custom properties from the first file using the name/expression
#  hash tables.

Import-Csv -Path c:\file2.csv | Select-Object *,@{
  Name="ABC"; Expression={$File1Values[$_.KeyColumn].ABC}
}, @{
  #You can abbreviate Name/Expression
  N="DEF"; E={$File1Values[$_.KeyColumn].DEF}
} | Export-Csv -Path c:\OutFile.csv

对于最后一部分,您还可以使用这些技术中的任何一种The Many Ways to Create a Custom Object 来创建自定义对象,我选择了“Select-Object”方法,因为您只需重建来自第一个文件(以更复杂的语法为代价)。

如果您在 V3 上并且想要使用新的 [PsCustomObject] 类型加速器,最后一点应该是这样的(注意您必须手动添加文件 1 和文件 2 属性):

#Import the second file and make a custom object with properties from both files

Import-Csv -Path c:\file2.csv | ForEach-Object {
  [PsCustomObject]@{
    ABC = $File1Values[$_.KeyColumn].ABC;
    DEF = $File1Values[$_.KeyColumn].DEF;
    UVW = $_.UVW;
    XYZ = $_.XYZ;
  }
} | Export-Csv -Path c:\OutFile.csv

【讨论】:

  • 非常感谢您提供的帮助。然而,我才意识到,CSV 中的许多标头不仅仅是一个单词,如下所示:“Object ID”、“Volume”、“Aggregate”、“Storage Server”、“Used”、“Total”、“Used” (%)" 在这种情况下,键是“对象 ID”。我将上面的“KeyColumn”替换为“Object ID”,但它似乎不起作用。我收到以下提示:为以下参数提供值:进程 [0]:顺便说一句,我必须将 -Header 附加到 Import-Csv 命令,否则会抛出错误。再次感谢您的帮助。
  • 您需要在其中包含空格的列/属性名称周围使用 ":$File1Values[$_."Object ID"]."Storage Server"
  • 我刚刚使用您列出的标题进行了仔细检查,并且我可以很好地导入它们,并且如果我在脚本中的任何复杂标题名称周围加上“”,脚本就可以工作。 ForEach-Object 是我使用的唯一将 -Process 作为参数的命令,请确保您的开头 { 与 ForEach-Object 命令位于同一行。
猜你喜欢
  • 2017-12-19
  • 2016-03-25
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 2018-09-15
相关资源
最近更新 更多