在大型文本文件中查找和替换许多字符串的有效方法

时间:2017-10-26 06:22:33

标签: powershell powershell-v2.0 powershell-v3.0

Text文件包含时域分析的软件输出。模拟10800秒,考虑50个节点。我们在 540 MB文本文件和450万行中替换了540,000个字符串。

目前预计需要4天以上的时间。出了点问题。不知道是什么。请建议我一个更有效的方法。

以下是查找和替换的功能。 要替换字符串,脚本会逐行浏览原始文本文件,同时会生成包含已替换字符串的重复文件因此,在脚本结尾处将生成另一个包含450万行的540 MB文件

Function ReplaceStringsInTextFile
{
    $OutputfilebyLine = New-Object -typename System.IO.StreamReader $inputFilePathFull
    $uPreviousValue = 0
    $time = 60
    $u = 0; $LastStringWithoutFindResult = 0
    $lineNumber = 0
    while ($null -ne ($line = $OutputfilebyLine.ReadLine())) {  
        $lineNumber = $lineNumber + 1
        if ($time -le $SimulationTimeSeconds)  # time simulation start and end checks 
        {

            # 10800 strings corresponds to one node 
            # there are 50 nodes.. Thus 540,000 values 

            # $StringsToFindFileContent contains strings to find 540,000 strings
            # $StringsToReplaceFileContent contains strings to replace 540,000 strings

            $StringToFindLineSplit = -split $StringsToFindFileContent[$time-60]
            $StringToReplaceLineSplit = -split $StringsToReplaceFileContent[$time-60]
            if($u -le $NumberofNodes-1)
            {
                $theNode = $Nodes_Ar[$u] 
                $StringToFindvalue = $StringToFindLineSplit[$u]
                $StringToReplacevalue = $StringToReplaceLineSplit[$u]
                if (($line -match $theNode) -And ($line -match $StringToFindvalue)){
                    $replacedLine = $line.replace($StringToFindvalue,$StringToReplacevalue) 

                    add-content -path $WriteOutputfilePathFull -value "$replacedLine"
                    $uPreviousValue = $u                      
                    $checkLineMatched = 1
                    if (($line -match $LastNodeInArray)) {
                        $time = $time + 1 
                        $LastStringWithoutFindResult = 0
                    }
                } elseIf (($line -match $LastNodeInArray) -And ($checkLineMatched -eq 0)) {
                    $LastStringWithoutFindResult =  $LastStringWithoutFindResult + 1
                } else { 
                    #"Printing lines without match"
                    add-content -path $WriteOutputfilePathFull -value "$line"
                    $checkLineMatched = 0
                }
            }

            if ($checkLineMatched -eq 1) {
                # incrementing the value of node index to next one in case the last node is found 
                $u = $uPreviousValue + 1
                if ($u -eq $Nodes_Ar.count) {
                        $u = 0
                        $timeElapsed = (get-date -displayhint time) - $startTime 
                        "$($timeElapsed.Hours) Hours $($timeElapsed.Minutes) Minutes $($timeElapsed.Seconds) Seconds"
                }
            }
        }
        # Checking if the search has failed for more than three cycles
        if ($LastStringWithoutFindResult -ge 5) { # showing error dialog in case of search error
            [System.Windows.Forms.MessageBox]::Show("StringToFind Search Fail. Please correct StringToFind values. Aborting now" , "Status" , 0)
            $OutputfilebyLine.close()
        }
    }   
    $OutputfilebyLine.close()
}

以上功能是脚本的最后一部分。这花费的时间最多。 我在1年前不到10小时就运行了这个脚本。

更新脚本在4小时后加速运行,突然完成投影的时间从4天减少到3小时以下。该脚本在7小时9分钟内完成运行。但是我不确定是什么造成了速度的突然变化,除了询问堆栈溢出的问题:)

1 个答案:

答案 0 :(得分:0)

根据https://stackoverflow.com/users/478656/tessellatingheckler的建议 我已经避免使用

一次写一行
add-content -path $WriteOutputfilePathFull -value "$replacedLine"

相反,我现在使用add-content

一次写一万行
$tenThousandLines = $tenThousandLines + "`n" + $replacedLine

在适当的时候,我使用add-content一次写下10,000行,如下所示。 if块遵循我的方法逻辑

 if ($lineNumber/10000 -gt $tenThousandCounter){
        clear-host
        add-content -path $WriteOffpipeOutputfilePathFull -value "$tenThousandLines"
        $tenThousandLines = ""
        $tenThousandCounter = $tenThousandCounter + 1
}

我在尝试一次添加15,000或25,000行时遇到了memmory异常错误。使用此操作后,操作所需的时间从7小时减少到5小时。而在另一个时间到2小时36分钟