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

Powershell版本的cut-d在处理大文件时速度很慢,我是否错过了快速的方法?

  •  1
  • Adriaantje  · 技术社区  · 8 月前

    我有一个非常大(>100k行)的文件要拆分 : .
    然后,我想丢弃第一个项目,留下其余的。例如, foo:bar:baz 成为 bar:baz .
    如果我这样做 cut -d ':' -f2- myfile.txt > newfile.txt 它在几毫秒内完成。
    我在Powershell中尝试了几种方法,但还没有看到一种完成。几分钟后,我中止了,因为这个脚本等不了那么久。当然,有更好/更快的方法可以做到这一点,但我似乎找不到。

    到目前为止,我发现的最有希望的方法是这样的:

    $reader = [System.IO.File]::OpenText("myfile.txt")
    try {
        for() {
            $line = $reader.ReadLine()
            if ($line -eq $null) { break }
            $split = $line.Split(":")
            $join = $split[1..($split.Length-1)] -join ":"
            Add-Content -Path "newfile.txt" -Value "$join"
        }
    }
    finally {
        $reader.Close()
    }
    

    请提供帮助/建议。

    1 回复  |  直到 8 月前
        1
  •  2
  •   Santiago Squarzon    8 月前

    在这个答案的两个例子中,你都可以使用正则表达式而不是拆分,这样会更有效。有关正则表达式的详细信息,您可以查看: https://regex101.com/r/iGfHWp/1 .

    • 如果您可以一次读取所有文件内容,那么您可以执行以下操作:
    (Get-Content myfile.txt -Raw) -replace '(?m)^.+?:' |
        Set-Content newfile.txt
    
    • 如果你不能一次读取所有文件内容,需要尽可能低的内存使用率,但仍然保持高效,那么我建议 File.ReadLines + StreamWriter :
    try {
        # use absolute path always in this case, i.e.:
        # `newfile.txt` should be `X:\path\to\newfile.txt`
        $writer = [System.IO.StreamWriter] 'newfile.txt'
        $re = [regex]::new(
            '^.+?:', [System.Text.RegularExpressions.RegexOptions]::Compiled)
    
        foreach ($line in [System.IO.File]::ReadLines('myfile.txt')) {
            $writer.WriteLine($re.Replace($line, ''))
        }
    }
    finally {
        if ($writer) {
            $writer.Dispose()
        }
    }