Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am writing a script for customising a configuration file. I want to replace multiple instances of strings within this file, and I tried using powershell to do the job. It works fine for a single replace, but doing multiple replaces is very slow because each time it has to parse the whole file again, and this file is very large. The script looks like this:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1new'
    } | Set-Content $destination_file

What I want is something like this, but I don't know how to write it:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa'
    $_ -replace 'something2', 'something2bb'
    $_ -replace 'something3', 'something3cc'
    $_ -replace 'something4', 'something4dd'
    $_ -replace 'something5', 'something5dsf'
    $_ -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file
share|improve this question
add comment

3 Answers

up vote 46 down vote accepted

One option is to chain the -replace operations together. The ` at the end of each line escapes the newline, causing PowerShell to continue parsing the expression on the next line:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa' `
       -replace 'something2', 'something2bb' `
       -replace 'something3', 'something3cc' `
       -replace 'something4', 'something4dd' `
       -replace 'something5', 'something5dsf' `
       -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file

Another option would be to assign an intermediate variable:

$x = $_ -replace 'something1', 'something1aa'
$x = $x -replace 'something2', 'something2bb'
...
$x
share|improve this answer
 
Thanks, this is the method I used. –  Ivo Bosticky Aug 5 '10 at 13:18
 
+1 I am using it too :) –  cad Jul 18 '12 at 11:47
 
Can $original_file == $destination_file? As in I am modifying the same file as my source? –  cquadrini May 8 at 2:58
 
Because of the way PowerShell cmdlets stream their input/ouput, I don't believe it would work to write out to the same file in the same pipeline. However, you could do something like $c = Get-Content $original_file; $c | ... | Set-Content $original_file. –  dahlbyk May 10 at 13:34
add comment

to get the post by George Howarth working properly with more than one replacement you need to remove the break, assign the output to a variable ($line) and then output the variable.

$lookupTable = @{
'something1' = 'something1aa' 
'something2' = 'something2bb' 
'something3' = 'something3cc' 
'something4' = 'something4dd' 
'something5' = 'something5dsf' 
'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object { 
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line = $line -replace $_.Key, $_.Value
        }
    }
   $line
} | Set-Content -Path $destination_file
share|improve this answer
add comment

Assuming you can only have one 'something1' or 'something2' etc per line, you can use a lookup table:

$lookupTable = @{
    'something1' = 'something1aa' 
    'something2' = 'something2bb' 
    'something3' = 'something3cc' 
    'something4' = 'something4dd' 
    'something5' = 'something5dsf' 
    'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object { 
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line -replace $_.Key, $_.Value
            break
        }
    }
} | Set-Content -Path $destination_file

If you can have more than one of those, just remove the break in the if statement.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.