包含150,000个文件的源文件夹,在Win 2003服务器中大小约为4 GB。需要递归替换XML文件中的少数模式。
$files = Get-ChildItem "source_folder" -Filter *.xml -Recurse
Write-Host $files.count "files present in source"
foreach ($file in $files) {
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "string1", "replacement1" } | Foreach-Object { $_ -replace "string2", "replacement2" } | Set-Content $file.PSPath
Write-Host $file.PSPath " modified"
}
此代码需要一个多小时才能完成。实现这一目标的最佳方法是什么?减少所用时间有哪些选择?使用PERL更好吗?建议会有很大的帮助!
答案 0 :(得分:1)
你可以使用perl one-liner - 类似于:
perl -p -i -e 's/oldstring/newstring/g' `grep -ril --include *.xml oldstring *`
如果您想保留原始文件的备份:
perl -p -i'.bak' -e 's/oldstring/newstring/g' `grep -ril --include *.xml oldstring *`
答案 1 :(得分:1)
首先,您应该使用.NET Classes。 仅此一项就可以为您节省大量时间。你真的应该使用v3版本替换(.replace方法)。它更快。
所以它看起来像这样:
foreach ($file in $files) {
$content = [System.IO.File]::ReadAllText($file).Replace("val1","val2")
[System.IO.File]::WriteAllText($file, $content)
Write-Host $file.PSPath " modified"
}
答案 2 :(得分:1)
尝试像这样修改你的代码:
$files = Get-ChildItem "C:\temp" -Filter *.xml -Recurse -File
foreach ($file in $files)
{
(Get-Content $file.FullName) | Foreach-Object {
$_ -replace 'something1', 'something1aa' `
-replace 'something2', 'something2bb' `
-replace 'something3', 'something3cc' `
-replace 'something4', 'something4dd' `
-replace 'something5', 'something5dsf' `
-replace 'something6', 'something6dfsfds'
} | Set-Content $file.FullName
Write-Host $file.FullName " analysed"
}
答案 3 :(得分:-1)
虽然我没有相同的资源来测试这个,但我怀疑如果你避免这么多管道会运行得更快,如下:
$files = Get-ChildItem "source_folder" -Filter *.xml -Recurse
Write-Host $files.count "files present in source"
foreach ($file in $files) {
$s = Get-Content $file.PSPath
$s = $s -replace "string1", "replacement1") -replace "string2", "replacement2"
Set-Content $file.PSPath -Value $s
Write-Host $file.PSPath " modified"
}
管道机制有一些应该避免的开销。我很想知道它对你的案子有多大的不同。
另外一点,可能最好在Set-Content命令中添加-Encoding
值来控制输出文件的编码方式。