简体   繁体   中英

Optimizing a replace operation in multiple files in powershell

I wrote the script below to iterate through files in a directory, then do a replace based on a hash table (which will actually contain 30 key/values, not 4 as shown here). This is a very, very large directory and the files are somewhat large so I want to make sure this is as optimized as possible, but I'm not that proficient in powershell. Is this is it or do I need to refactor, and if so, what should I do? Thank you.

Get-ChildItem 'C:\temp' -Filter *.txt | 
Foreach-Object {
    $lookupTable = @{
        'a' = '1'
        'b' = '2'
        'c' = '3'
        'd' = '4'
    }
    $file = $_
    Write-Host "$file"
    (Get-Content -Path $file -Raw) | ForEach-Object {
        $line = $_
        $lookupTable.GetEnumerator() | ForEach-Object {
            if ($line -match $_.Key) {
            $line = $line -replace $_.Key, $_.Value
            }
        }
    $line
    } | Set-Content -Path $file
}

Here are some measured test cases (

  • a 5000-iterations loop instead of getting multiple files
  • a scalar value "ano, cosi bude jinak" instead of reading each of them

)

$lookupTable = @{
    'a' = '1'
    'b' = '2'
    'c' = '3'
    'd' = '4'
}
'original approach ', ( Measure-Command {
    for ( $i = 0; $i -lt 5000; $i++ ) {                 # get-childitem
        $line = "ano, cosi bude jinak"                  # get-content
        $lookupTable.GetEnumerator() | ForEach-Object {
            if ($line -match $_.Key) {
                $line = $line -replace $_.Key, $_.Value
            }
        }
        $line
    }
}).TotalSeconds, $line -join "   "

'@mhu: without IF  ', ( Measure-Command {
    for ( $i = 0; $i -lt 5000; $i++ ) {
        $line = "ano, cosi bude jinak"
        $lookupTable.GetEnumerator() | ForEach-Object {
            $line = $line -replace $_.Key, $_.Value
        }
        $line
    }
}).TotalSeconds, $line  -join "   "

'HashTable -> Array', ( Measure-Command {
    $lookupArrayCount = $lookupTable.Count
    $lookupArray = New-Object 'array[]' $lookupArrayCount
    $j = 0
    $lookupTable.GetEnumerator() | ForEach-Object {
        $lookupArray[$j] = @( $_.Key, $_.Value )
        $j++
    }
    for ( $i = 0; $i -lt 5000; $i++ ) {
        $line = "ano, cosi bude jinak"
        for ( $j = 0; $j -lt $lookupArrayCount; $j++ ) {
            $line = $line -replace $lookupArray[$j]
        }
        $line
    }
}).TotalSeconds, $line -join "   "

Output :

D:\PShell\SO\56587351.ps1
 original approach 1,8059152 1no, 3osi 2u4e jin1k @mhu: without IF 1,5973162 1no, 3osi 2u4e jin1k HashTable -> Array 0,3225432 1no, 3osi 2u4e jin1k 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM