我可以使用Where-Object跳过CSV文件的标题行吗?

时间:2018-05-16 19:12:35

标签: powershell

我想使用以下脚本将巨大的CSV文件缩减为有用的状态,但它消除了CSV的标题行。我从阅读过去的问题/解决方案中了解到,我可以使用Select -Skip 1Select -Skip 1来保留标题,但我不确定如何优雅地将Select集成到我的脚本中。我是否需要从头开始,或者有人有一个简单的解决方案吗?

$SourceFile = 'C:\Temp\Monthly_Report.CSV'
$Pattern = '.GBL|.aspx'

(Get-Content $SourceFile) | Where-Object {
    $_ -match $Pattern
} | Set-Content $SourceFile

在运行脚本之前,这是“Monthly_Report.CSV”的内容:

Monthy_Report.CSV

3 个答案:

答案 0 :(得分:1)

您根本不需要使用-skip参数来保留标头。我想你是在误解它。 您的内容在内容中丢失的原因是因为它与您的$ Pattern变量不匹配并且它被过滤掉了。

你需要这样做:

$header = (Get-Content $SourceFile) | Select-Object -First 1
Write-Output $header 

$content = (Get-Content $SourceFile) | Where-Object { $_ -match $Pattern } 
$header + "`n" + $content | Set-Content $SourceFile

答案 1 :(得分:1)

您的问题有几种解决方案。

  • 使用Import-CsvExport-Csv,它会将输入CSV转换为对象列表并返回。

    (Import-Csv $SourceFile) | Where-Object {
        $_.SomeProperty -match $Pattern
    } | Export-Csv $SourceFile -NoType
    

    这可以说是最干净的方法,尽管不是最有效的方法。转换使得这比纯文本处理慢。尽管如此,这是最易读的代码,所以除非遇到严重的性能问题,否则我建议使用它。

  • 由于您无论如何都要将整个文件读入内存(由于Get-Content在括号中),您也可以将内容存储在变量中并有选择地将其写回:

    $data = Get-Content $SourceFile
    
    $data | Select-Object -First 1 | Set-Content $SourceFile
    $data | Where-Object {
        $_ -match $Pattern
    } | Add-Content $SourceFile
    
  • Where-Object scriptblock不仅可以包含条件,还可以包含其他语句,例如赋值操作,因此您可以使用“第一行”指示符,如下所示:

    $script:firstline = $true
    (Get-Content $SourceFile) | Where-Object {
        $script:firstline -or $_ -match $Pattern
        $script:firstline = $false
    } | Set-Content $SourceFile
    
  • 您可以在正则表达式中包含标题匹配:

    $Pattern = '^UserID|.GBL|.aspx'
    
    (Get-Content $SourceFile) | Where-Object {
        $_ -match $Pattern
    } | Set-Content $SourceFile
    

    但这对我来说是相当黑客的,所以我不建议这样做。

答案 2 :(得分:0)

这是一个简单的解决方案,它使用多个赋值来从主体中拆分标题,并依赖于-match对集合起作用的事实:

$SourceFile = 'C:\Temp\Monthly_Report.CSV'
$Pattern = '\.GBL|\.aspx'

$header, $body = Get-Content $SourceFile
$body =  @($body) -match $Pattern
$header, $body | Set-Content $SourceFile