代码之家  ›  专栏  ›  技术社区  ›  adam78

Windows PowerShell-逐行删除行号

  •  0
  • adam78  · 技术社区  · 6 年前

    我有一个大的csv文件(1.6GB)。如何删除特定行,如1005行?

    1 回复  |  直到 6 年前
        1
  •  6
  •   mklement0    6 年前

    注意:下面的解决方案从任何基于文本的文件中逐行删除一行。AS marsze 指出,其他考虑可能适用于 猪瘟病毒 文件,必须注意不要删除标题行,如果行具有内嵌换行符的值,则行可以跨多行;在这种情况下,使用csv解析器是更好的选择。

    如果性能不是最重要的,这里是 基于内存友好管道的方法 做到这一点:

    Get-Content file.txt | 
      Where-Object ReadCount -ne 1005 |
        Set-Content -Encoding Utf8 new-file.txt
    

    Get-Content 添加(名称有点模糊) .ReadCount 属性设置为它输出的每一行,其中包含 1 -基于行号。

    • 请注意,输入文件的字符编码不是由 获取内容 ,所以你应该控制 Set-Content 'ST输出显式编码,如上图所示,以utf-8为例。

    • 如果不将整个文件作为一个整体读取到内存中,则必须输出到 新的 文件,至少是临时的;可以用临时输出文件替换原始文件
      Move-Item -Force new-file.txt file.txt


    更快,但内存密集的替代方案 基于直接使用.NET框架,它还允许您就地更新文件:

    $file = 'file.txt'
    $lines = [IO.File]::ReadAllLines("$PWD/$file")
    Set-Content -Encoding UTF8 $file -Value $lines[0..1003 + 1005..($lines.Count-1)]
    
    • 注意使用的必要性 "$PWD/$file" 即,将当前目录路径显式地预先设置为存储在 $file ,因为.NET框架对当前目录的概念与PowerShell的不同。

      • 同时 $lines = Get-Content $file 在功能上等同于 $lines = [IO.File]::ReadAllLines("$PWD/$file") 它的表现明显较差。
    • 0..1003 从创建索引数组 0 1003 ; + 将该数组与索引连接起来 1005 通过输入数组的其余部分;请注意,数组索引是 -基于,而行号是 基础。

    • 还要注意结果数组是如何传递给 设置内容 作为一个 直接论证 通过 -Value 比通过管道更快( ... | Set-Content ... ,其中将执行逐元素处理。


    最后, 一种比基于管道的方法更快的内存友好方法 :

    $file = 'file.txt'
    $outFile = [IO.File]::CreateText("$PWD/new-file.txt")
    $lineNo = 0
    try {
      foreach ($line in [IO.File]::ReadLines("$PWD/$file")) {
        if (++$lineNo -eq 1005) { continue }
        $outFile.WriteLine($line)
      }
    } finally {
      $outFile.Dispose()
    }
    

    与基于管道的命令一样,以后可能必须用新文件替换原始文件。

    推荐文章