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

如何从powershell中的多个csv文件中删除特定行?,powershell,rows,Powershell,Rows,您好,我正在寻找一种有效的方法来删除多个csv文件的第二行和最后一行?我在一个目录中有大约5000个文件。 下面的代码将删除第一行。如果我使用参数-跳过2。它将跳过前两行,但我需要保留第一行并删除第二行和最后一行。我也不确定获取内容集内容是否适合处理如此大量的文件 foreach ($file in gci *.csv ){ (gc $file) | Select-Object -Skip 1 | set-content $file } 也许不是最好的方法,但您可以使用-Index并计算所需

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

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

也许不是最好的方法,但您可以使用-Index并计算所需的行

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

对于数组,索引从0开始,所以我们取那个值并跳过记录1。等我们把剩下的减去最后一个-索引采用和整数数组,因此我们创建一个值为0的单元素数组,并将从2开始的索引追加到文件末尾减去-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文件时没有打开任何内容

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

Col1,Col2,Col3,Col4
---- ---- ---- ----
Data,data,data,data
data,data,data,data
Log Created: 02/04/2015
您希望在末尾删除行和日志创建注释的位置

Edit2:更好的解决方案可能是获取文件的内容,输出第一行,然后通过末尾减去1行输出第3行,并将其附加到同一个文件中。比如:

(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
}

就表演说几句。我使用@TheMadTechnician方法获取内容,并比较了3种不同的输出编写方法。每次测试我都使用100个1MB的输入文件。结果如下:

使用Out文件覆盖内容花费了1分32秒

dir *.txt | %{
    $content = gc $_.FullName
    $content | select -First 1 | Out-File $_.FullName -Force
    $content[2..($content.count -2)]|Out-File $_.FullName -Append
}
使用“设置内容”覆盖内容花费了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更新的记录。谢谢@ThemadTechnician我这里有错误。无法将选择值转换为System.int32类型。输入字符串的格式不正确耶。。。我又犯了一个错误,把我的测试代码和你的代码混在一起了。。如果你想再看看。。。也许它的性能更好谢谢你,你的代码比MadTechnician快了45%,这在处理大量文件时确实节省了很多时间。类似的错误在这里。无法将参数绑定到参数路径,因为它为null$contents=gc$fileSorry,在更改ForEach方法后,我忘记重新分配n$file。我现在已经更新了,应该可以用了。谢谢,可以用了。唯一的问题是它相当慢。对于5000个文件,运行时间超过7分钟。在谷歌上,我发现IO.StreamReader可以读取大量文件,但我不确定它是否可以用于我的案例。感谢您的帮助,Stephen。最后一段代码真的很快。看起来你的PS真的很好。你能帮我再解决一个问题吗?是否可以使用类似的代码将存储在这些文件的第一列中的日期格式从m/d/yyyy更改为mm/dd/yyyy,或者我需要发布另一个问题?我会发布另一个问题,因为它是另一个问题。尝试查看get date、import csv、export csv和自定义datetime格式提供程序,看看您是否可以首先找到它。很高兴知道我们的文件速度太慢了。我不知道,但将来一定会考虑到这一点!非常好的回答Hello Stephen。我刚刚发布了我上面提到的那个问题。如果您仔细检查我的代码并提出改进建议,那将是非常棒的。非常感谢。约翰