在大型搜索/替换操作中,PowerShell很慢(比Python慢​​得多)?

Kei*_*ith 21 python powershell performance replace

我有265个CSV文件,总记录(行数)超过400万,需要在所有CSV文件中进行搜索和替换.我在下面有一段我的PowerShell代码可以执行此操作,但执行操作需要17分钟:

ForEach ($file in Get-ChildItem C:\temp\csv\*.csv) 
{
    $content = Get-Content -path $file
    $content | foreach {$_ -replace $SearchStr, $ReplaceStr} | Set-Content $file
}
Run Code Online (Sandbox Code Playgroud)

现在我有以下Python代码执行相同的操作,但执行时间不到1分钟:

import os, fnmatch

def findReplace(directory, find, replace, filePattern):
    for path, dirs, files in os.walk(os.path.abspath(directory)):
        for filename in fnmatch.filter(files, filePattern):
            filepath = os.path.join(path, filename)
            with open(filepath) as f:
                s = f.read()
            s = s.replace(find, replace)
            with open(filepath, "w") as f:
                f.write(s)

findReplace("c:/temp/csv", "Search String", "Replace String", "*.csv")
Run Code Online (Sandbox Code Playgroud)

为什么Python方法效率更高?我的PowerShell代码是无效的,还是Python在文本操作方面只是一种更强大的编程语言?

And*_*ndi 11

试试这个PowerShell脚本.它应该表现得更好.在缓冲流中读取文件时,RAM的使用也少得多.

$reader = [IO.File]::OpenText("C:\input.csv")
$writer = New-Object System.IO.StreamWriter("C:\output.csv")

while ($reader.Peek() -ge 0) {
    $line = $reader.ReadLine()
    $line2 = $line -replace $SearchStr, $ReplaceStr
    $writer.writeline($line2)
}

$reader.Close()
$writer.Close()
Run Code Online (Sandbox Code Playgroud)

这会处理一个文件,但您可以使用它来测试性能,如果它更可接受,则将其添加到循环中.

或者,您可以使用Get-Content多个行读入内存,执行替换,然后使用PowerShell管道编写更新的块.

Get-Content "C:\input.csv" -ReadCount 512 | % {
    $_ -replace $SearchStr, $ReplaceStr
} | Set-Content "C:\output.csv"
Run Code Online (Sandbox Code Playgroud)

为了获得更多性能,您还可以编译正则表达式(-replace使用正则表达式),如下所示:

$re = New-Object Regex $SearchStr, 'Compiled'
$re.Replace( $_ , $ReplaceStr )
Run Code Online (Sandbox Code Playgroud)

  • @pst Get-Content允许流式传输,这意味着管道中的下一个cmdlet可以在它进入管道后立即开始工作 - 即使很快就会有更多数据.当您分配到$ content时,您将失去该功能,因为整个get-content必须在下一个操作发生之前完成. (2认同)

mjo*_*nor 5

我看到了很多:

$content | foreach {$_ -replace $SearchStr, $ReplaceStr} 
Run Code Online (Sandbox Code Playgroud)

-replace运算符将立即处理整个数组:

$content -replace $SearchStr, $ReplaceStr
Run Code Online (Sandbox Code Playgroud)

并且比一次迭代一个元素要快得多.我怀疑这样做可能会让你更接近苹果对苹果的比较.