您好我正在寻找从多个csv文件中删除第二行和最后一行的有效方法吗?我在目录中有大约5000个文件。 下面的代码将删除第一行。如果我使用参数-skip 2.它将跳过前两行,但我需要保留第一行并删除第二行和最后一行。我也不确定get-content set-content是否适合采用如此大量的文件。
foreach ($file in gci *.csv ){
(gc $file) | Select-Object -Skip 1 | set-content $file
}
答案 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
}