我有一个包含~3000个文本文件的目录,我正在定期搜索并替换这些文本文件,因为我将程序转换为新服务器。
每个文本文件平均可能有~3000行,我需要一次搜索文件大约300 - 1000个术语。
我正在替换与我正在搜索的字符串相关的服务器前缀。因此,对于每个csv条目,我正在寻找Search_String
,\\Old_Server\"Search_String"
并确保在程序完成后,结果为"\\New_Server\Search_String"
。
我拼凑了一个PowerShell程序,它有效。但它太慢我从未见过它完整。
有什么建议让它更快?
编辑1: 我按照建议更改了get-content,但是仍然花了3分钟搜索两个文件(~8000行)以获得9个单独的搜索词。我还是要搞砸了;如果手动完成9次,记事本++搜索和替换仍然会更快。
我不知道如何摆脱第一个(Get-Content),因为我想在对其进行任何更改之前复制一份备份文件。
编辑2: 所以这快一个数量级;它在10秒钟内搜索文件。但现在它不会对文件进行更改,而只搜索目录中的第一个文件!我没有改变那段代码,所以我不知道它为什么会破坏。
编辑3: 成功!我调整了下面发布的解决方案,使其更快,更快。它现在在几秒钟内搜索每个文件。我可以反转循环顺序,以便将文件加载到数组中,然后搜索并替换CSV中的每个条目,而不是相反。如果我让它发挥作用我会张贴。
最终脚本在下面供参考。
#get input from the user
$old = Read-Host 'Enter the old cimplicity qualifier (F24, IRF3 etc'
$new = Read-Host 'Enter the new cimplicity qualifier (CB3, F24_2 etc)'
$DirName = Get-Date -format "yyyy_MM_dd_hh_mm"
New-Item -ItemType directory -Path $DirName -force
New-Item "$DirName\log.txt" -ItemType file -force -Value "`nMatched CTX files on $dirname`n"
$logfile = "$DirName\log.txt"
$VerbosePreference = "SilentlyContinue"
$points = import-csv SearchAndReplace.csv -header find #Import CSV File
#$ctxfiles = Get-ChildItem . -include *.ctx | select -expand fullname #Import local directory of CTX Files
$points | foreach-object { #For each row of points in the CSV file
$findvar = $_.find #Store column 1 as string to search for
$OldQualifiedPoint = "\\\\"+$old+"\\" + $findvar #Use escape slashes to escape each invidual bs so it's not read as regex
$NewQualifiedPoint = "\\"+$new+"\" + $findvar #escape slashes are NOT required on the new string
$DuplicateNew = "\\\\" + $new + "\\" + "\\\\" + $new + "\\"
$QualifiedNew = "\\" + $new + "\"
dir . *.ctx | #Grab all CTX Files
select -expand fullname | #grab all of those file names and...
foreach {#iterate through each file
$DateTime = Get-Date -Format "hh:mm:ss"
$FileName = $_
Write-Host "$DateTime - $FindVar - Checking $FileName"
$FileCopied = 0
#Check file contents, and copy matching files to newly created directory
If (Select-String -Path $_ -Pattern $findvar -Quiet ) {
If (!($FileCopied)) {
Copy $FileName -Destination $DirName
$FileCopied = 1
Add-Content $logfile "`n$DateTime - Found $Findvar in $filename"
Write-Host "$DateTime - Found $Findvar in $filename"
}
$FileContent = Get-Content $Filename -ReadCount 0
$FileContent =
$FileContent -replace $OldQualifiedPoint,$NewQualifiedPoint -replace $findvar,$NewQualifiedPoint -replace $DuplicateNew,$QualifiedNew
$FileContent | Set-Content $FileName
}
}
$File.Dispose()
}
答案 0 :(得分:2)
如果我正确读取此内容,您应该能够将3000行文件读入内存,并将这些替换作为数组操作,从而无需遍历每一行。您还可以将这些替换操作链接到单个命令中。
dir . *.ctx | #Grab all CTX Files
select -expand fullname | #grab all of those file names and...
foreach {#iterate through each file
$DateTime = Get-Date -Format "hh:mm:ss"
$FileName = $_
Write-Host "$DateTime - $FindVar - Checking $FileName"
#Check file contents, and copy matching files to newly created directory
If (Select-String -Path $_ -Pattern $findvar -Quiet ) {
Copy $FileName -Destination $DirName
Add-Content $logfile "`n$DateTime - Found $Findvar in $filename"
Write-Host "$DateTime - Found $Findvar in $filename"
$FileContent = Get-Content $Filename -ReadCount 0
$FileContent =
$FileContent -replace $OldQualifiedPoint,$NewQualifiedPoint -replace $findvar,$NewQualifiedPoint -replace $DuplicateNew,$QualifiedNew
$FileContent | Set-Content $FileName
}
}
另一方面,Select-String将文件路径作为参数,因此您不必执行Get-Content
,然后将其传递给Select-String
。
答案 1 :(得分:1)
是的,您可以通过不使用Get-Content
来更快地使用...而是使用Stream Reader。
$file = New-Object System.IO.StreamReader -Arg "test.txt"
while (($line = $file.ReadLine()) -ne $null) {
# $line has your line
}
$file.dispose()
答案 2 :(得分:0)
我想使用PowerShell并创建一个类似下面的脚本:
$filepath = "input.csv"
$newfilepath = "input_fixed.csv"
filter num2x { $_ -replace "aaa","bbb" }
measure-command {
Get-Content -ReadCount 1000 $filepath | num2x | add-content $newfilepath
}
我的笔记本电脑花了19分钟来处理6.5Gb文件。下面的代码是批量读取文件(使用ReadCount)并使用应该优化性能的过滤器。
然后我尝试了FART并在3分钟内做了同样的事情!相当不同!