使用PowerShell在csv中重新格式化列名

时间:2015-08-17 17:04:54

标签: powershell csv

问题

如何根据公式或子例程重新格式化未知的CSV列名称(例如,通过运行trim或regex或其他内容将列" Arbitrary Column Name "重命名为"Arbitrary Column Name"),同时保留数据?

目标

我正在尝试或多或少地清理手工生成(或至少是手工编辑的)csv文件中的列(名称),这些文件需要由现有PowerShell脚本处理。在这种特定情况下,列具有可以通过调用[String]::Trim()来删除的空格,或者可以使用适当的正则表达式忽略的空格,但是在导入时我无法想办法调用或使用这些技术或处理CSV。

短背景

历史上大多数文件和列都已正确输入到CSV中,但最近在处理过程中删除了一些列;我确定这是因为文件中包含一个空格(例如,Select-Object被告知获取"RFC",但Import-CSV被检索"RFC ",因此没有匹配的匹配。在这种情况下,告诉客户手动正确输入(虽然首选且更简单)不是一种选择。

考虑的选项

我可以手动处理文件的文本,但这是重新发明轮子的一种混乱且容易出错的方式。我想知道是否有Select-Object的语法允许更精确的列名匹配,但我找不到该信息。

我最接近的概念是在调用Select-Object时使用计算属性来重命名列,但我只能找到将已知列重命名为另一个已知列的方法。因此,这需要枚举列并精确匹配它们(首选)或更软的匹配(如通过正则表达式作为回退进行修剪或匹配后的比较)与预期的列名称,然后创建用于构造计算属性的名称映射集合从该信息中选择一个新对象。

这似乎会起作用,但它比我更喜欢它的工作,我不禁希望有一种更简单的方法,我无法通过谷歌找到。也许我应该尝试Bing?

3 个答案:

答案 0 :(得分:0)

示例文件

假设你有file.csv这样:

" RFC "
"1"
"2"
"3"

代码

现在尝试运行以下命令:

$CSV = Get-Content file.csv -First 2 | ConvertFrom-Csv
$FixedHeaders = $CSV.PSObject.Properties.Name.Trim(' ')
Import-Csv file.csv -Header $FixedHeaders |
    Select-Object -Skip 1 -Property RFC

输出

您将获得此输出:

RFC
---
1  
2  
3  

说明

首先,我们使用带有参数Get-Content的{​​{1}}来获取前两行。管道到-First 2将允许我们使用ConvertFrom-Csv访问标头。将PSObject.Properties.NameImport-Csv参数一起使用可以使用剪裁的标题。管道到-Header并使用Select-Object跳过原始标题。

答案 1 :(得分:0)

我不确定效率方面的比较,但我认为这有点硬化,只导入一次CSV。您可以使用@ lahell的方法和Get-Content -raw,但这已经完成并且有效,所以我将把它留给社区来确定哪个更好......

#import the CSV
$rawCSV = Import-Csv $Path

#get actual header names and map to their reformatted versions
$CSVColumns = @{}
$rawCSV | 
    Get-Member | 
    Where-Object {$_.MemberType -eq "NoteProperty"} |
    Select-Object -ExpandProperty Name | 
    Foreach-Object {

        #add a mapping to the original from a trimmed and whitespace-reduced version of the original
        $CSVColumns.Add(($_.Trim() -replace '(\s)\s+', '$1'), "$_")
    }

#Create the array of names and calculated properties to pass to Select-Object
$SelectColumns = @()
$CSVColumns.GetEnumerator() |
    Foreach-Object {
        $SelectColumns += {
            if ($CSVColumns.values -contains $_.key) {$_.key}
            else { @{Name = $_.key; Expression = $CSVColumns[$_.key]} }
        }
    }

$FormattedCSV = $rawCSV | 
    Select-Object $SelectColumns

这是手动复制到我无法运行它的计算机上,因此可能存在错误 - 我试图正确复制

答案 2 :(得分:0)

您可以使用gocsv https://github.com/DataFoxCo/gocsv查看csv的标题,然后您可以重命名标题,截取文件,交换列,连接,合并,您想要的任意数量的转换