powershell - 根据映射文件将列映射到新列名称

标签 powershell csv

更新:根据其他项目需求使用标记的首选解决方案。由于其他一些项目需求,我还对其进行了稍微修改,以丢弃源代码中未提供的任何列。

$refTable = @'
SourceColumn,TargetColumn
LastName,Last_Name
DOB,Date_Of_Birth
FirstName,First_Name
'@ | ConvertFrom-Csv

$source = @'
FirstName,DOB,NotInRefCol,LastName
Tom,06/07/1940,1,Jones
Bill,11/27/1955,2,Nye
William,04/01/1564,3,Shakespeare
'@ | ConvertFrom-Csv

$map = @{}
foreach($line in $refTable) {
    $map[$line.SourceColumn] = $line.TargetColumn
}

foreach($line in $source) {
    $out = [ordered]@{}
    foreach($prop in $line.PSObject.Properties) {
        if (!($refTable.SourceColumn.Contains($prop.Name))) {
            continue
        }
        if($newCol = $map[$prop.Name]) {
            $out[$newCol] = $prop.Value
            continue
        }
        $out[$prop.Name] = $prop.Value
    }
    [pscustomobject]$out
}

我有一组 CSV 格式的数据,我尝试根据映射文档中的列名称输出具有不同标题的相同数据。为了清楚起见,下面的列名称只是一个示例,但名称可能会有很大不同,并且顺序可能与映射文件中列的顺序不匹配。我最近没有做太多 Powershell 工作,所以我很难开始。我似乎无法弄清楚根据我正在查看的数据查找列名称的逻辑。例如,如果我执行 foreach ($row in $source) 我怎么知道如何对列进行排序?任何帮助将不胜感激!

示例: map.csv

SourceColumn,TargetColumn
LastName,Last_Name
DOB,Date_Of_Birth
FirstName,First_Name

source.csv

FirstName,LastName,DOB
Tom,Jones,06/07/1940
Bill,Nye,11/27/1955
William,Shakespeare,04/01/1564

期望的输出: 输出.csv

Last_Name,Date_Of_Birth,First_Name
Jones,06/07/1940,Tom
Nye,11/27/1955,Bill
Shakespeare,04/01/1564,William

最佳答案

注意:以下内容保留 source.csv 中的列顺序,并简单地替换新的列名称。这样可以对数据 CSV 进行相对快速的纯文本处理。

# Initialize an ordered hashtable.
$map = [ordered] @{}
# Fill it with the mapping of source to target column names.
Import-Csv map.csv | ForEach-Object { $map[$_.SourceColumn] = $_.TargetColumn }

# Read the data CSV into header line and all data lines.
# Note: You can speed this up with a somewhat obscure optimization:
#       $sourceHeader, $sourceData = (Get-Content -ReadCount 0 source.csv)
$sourceHeader, $sourceData = Get-Content source.csv

# Construct the new header line via the previously constructed
# map (ordered hashtable).
$newSourceHeader = ($sourceHeader -split ',' | ForEach-Object { $map[$_] }) -join ','

# Save the new header followed by the data lines to a (new) output
# file. Adjust the target file and -Encoding as needed.
Set-Content -Encoding utf8 output.csv -Value $newSourceHeader, $sourceData

如果您确实需要 map.csv 中的特定列排序,一个低效但简单的解决方案是将以下内容应用于由以下代码生成的 output.csv 文件:上面的代码:

Import-Csv output.csv |
  Select-Object (Import-Csv map.csv).TargetColumn |
    Export-Csv output_new.csv -Encoding utf8 -NoTypeInformation

关于powershell - 根据映射文件将列映射到新列名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71357411/

相关文章:

powershell - 选择对象与在同一对象上使用foreach之间的区别

php - 使用 CakePHP 批量导入 CSV 文件

python - PyQt5 tableView 显示底片是红色和 (x.xx)

wpf - 如何在列表框中显示 Powershell 输出数组

java - 如果输入 tsv 文件具有 ' or ",则 CSVListReader 从 tsv 文件读取会中断

python - Bigquery 加载时间戳时出错

python - 为什么我会收到此错误:Not allparameters wereused in the SQL statements using python?

asp.net - 无法提交配置更改,因为文件在磁盘上已更改

azure - 如何使用 PowerShell 检索逻辑应用工作流设置?

regex - 在指定字符串之前获取数字