【发布时间】:2021-09-13 17:10:14
【问题描述】:
我找到了一个相关的答案here,这确实很有帮助,但不是我想要的。我还查看了许多其他问题,但不幸的是,我无法弄清楚如何让它工作,而且看起来很简单。
基本上,我正在使用Import-Csv 并处理大量数据;但标题的名称有时会改变。因此,我不想重新编写我的代码,而是将我获得的标头映射到我的代码块中使用的标头。将最终数据输出为 CSV,我可以使用“更新的标题”保留它,或者,如果我能弄清楚如何轻松交换标题,我可以随时将它们交换回原来的样子。
假设我在 Excel 中有一个映射文件。我可以在行或列中进行映射,以更容易为准。对于第一个示例,我有行中的映射。当我使用Import-CSV 时,我想使用第 2 行的标题而不是第 1 行的标题。这是映射文件的内容:
所以基本上,如果我对这一切都进行硬编码,我会得到类似的东西:
$null, $headerRow, $dataRows = (Get-Content -Raw foo.csv) -split '(^.+\r?\n)', 2
ConvertFrom-Csv ($headerRow.Trim() -replace 'Identification', 'ID' -replace 'Revenue Code', 'Revenue_Code' -replace 'Total Amount for Line', 'Amount' -replace 'Total Quantity for Line', 'Qty'), $dataRows
除了我不想硬编码之外,我基本上是在寻找一种方法来使用替换映射文件或哈希表,如果我可以创建一个。
#Pseudo code for what I want
$hashtable = Get-Content mapping.xlsx
ConvertFrom-Csv ($headerRow.Trim() -replace $hashtable.Name, $hashtable.Value), $dataRows
我可能会失败并且找不到类似的示例,因为我试图灵活地使用映射文件的格式。我最初的想法是基本上将第一行视为一个字符串,并将整个字符串替换为第二行。但是哈希表的想法来自可能将映射重组为如下所示:
这里我基本上会-replace每个Source值和对应的Target值。
编辑如果您需要转换回来,请试一试 - 但请记住,只有在 Source:Target 值之间存在一对一关系时,它才会起作用。 p>
#Changing BACK to the original Headers...
$Unmap = @{}
(Import-Csv MappingTable.csv).ForEach({$Unmap[$_.Target] = $_.Source})
#Get string data from CSV Objects
$stringdata = $outputFixed | ConvertTo-CSV -NoTypeInformation
$headerRow = $stringdata[0]
$dataRows = $stringdata[1..($stringdata.Count-1)] -join "`r`n"
#Create new header data
$unmappedHeaderRow = ($headerRow -replace '"' -split ',').ForEach({'"' + $Unmap[$_] + '"'}) -join ','
$newdata = ConvertFrom-Csv $unmappedHeaderRow, $dataStrings
【问题讨论】:
-
如果列标题可以改变,列的顺序可能不会改变?
-
如果顺序和计数保持不变,我倾向于简单地使用数组索引在所需标题和当前标题之间进行引用。只需从
Import-Csv返回的第一个对象上剥离属性名称,就可以很容易地做到这一点。如果我的场景正确,我可以发布答案。 -
@Steven - 我不认为可以肯定地说顺序和计数将是相同的。一般来说,伯爵应该是一样的。顺序可能不同。
标签: powershell