如何从PowerShell中的多个csv文件中删除特定行?

时间:2015-02-04 21:21:05

标签: powershell rows

您好我正在寻找从多个csv文件中删除第二行和最后一行的有效方法吗?我在目录中有大约5000个文件。 下面的代码将删除第一行。如果我使用参数-skip 2.它将跳过前两行,但我需要保留第一行并删除第二行和最后一行。我也不确定get-content set-content是否适合采用如此大量的文件。

foreach ($file in gci *.csv ){
(gc $file) | Select-Object -Skip 1 | set-content $file
 }

3 个答案:

答案 0 :(得分:3)

关于表现的一句话。我使用@TheMadTechnician方法获取内容并比较了3种不同的输出方法。我为每个测试使用了100个1MB输入文件。以下是结果:

使用Out-File覆盖内容需要1分32秒。

dir *.txt | %{
    $content = gc $_.FullName
    $content | select -First 1 | Out-File $_.FullName -Force
    $content[2..($content.count -2)]|Out-File $_.FullName -Append
}

使用Set-Content覆盖内容需要37秒。

dir *.txt | %{
    $content = gc $_.FullName
    $output = @($content | select -First 1 )
    $output += $content[2..($content.count -2)]
    $output | Set-Content $_.FullName -Force
}

使用StreamWriter覆盖内容需要31秒。

dir *.txt | %{     
    $content = gc $_.FullName
    $output = @($content | select -First 1 )
    $output += $content[2..($content.count -2)]
    $sw = New-Object System.IO.StreamWriter($_.FullName,$false)
    $output | %{$sw.WriteLine($_)}
    $sw.close()
}

您可能希望针对您的特定情况研究这些不同的方法,但我一直发现Out-File远比Set-Content或StreamWriter慢。

答案 1 :(得分:1)

也许不是最好的方法,但你可以使用-Index并计算你想要的行。

foreach ($file in gci *.csv ){
    $data = gc $file
    $data | Select-Object -Index (,0 + (2..($data.Count - 2))) | set-content $file
}

对于数组,索引从0开始,所以我们采用那个并跳过记录1.在我们只剩下减去最后一个。 -Index采用整数数组,因此我们创建一个值为0的单个元素数组,并将索引从2添加到文件末尾减去最后一个(-2来自.Count的地方从1)开始。

答案 2 :(得分:1)

你很接近,我只是通过代码中的Where子句来跳过每个文件中的第1项和第-1项。像这样:

(gci *.csv )|ForEach{
    $file = $_
    $contents = gc $file
    $contents | Where{$_ -ne $contents[1] -and $_ -ne $contents[-1]} | out-file $file.fullname -force
}

我做了ForEach内联以确保GCI完成并且在您尝试执行Out-File时没有打开任何内容

编辑:我刚刚意识到我的代码存在一个潜在的缺陷,如果你有第2行或最后一行的重复行,那么这些行也会被删除。我写了这个,假设你有类似以下的东西想要清理:

Col1,Col2,Col3,Col4
---- ---- ---- ----
Data,data,data,data
data,data,data,data
Log Created: 02/04/2015

你想在最后删除---行和日志创建的注释。

Edit2:更好的解决方案可能是获取文件的内容,输出第一行,然后输出第3行到最后(减去1行)并将其附加到同一行文件。类似的东西:

(gci *.csv )|ForEach{
    $Path = $_.FullName
    $content = gc $Path
    $content|select -first 1|Out-File $Path -force
    $content[2..($content.count-2)]|Out-File $Path -Append
}