我想使用以下脚本将巨大的CSV文件缩减为有用的状态,但它消除了CSV的标题行。我从阅读过去的问题/解决方案中了解到,我可以使用Select -Skip 1
或Select -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”的内容:
答案 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-Csv
和Export-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