Cómo reemplazar varias cadenas en un archivo usando PowerShell

Estoy escribiendo un script para personalizar un archivo de configuración. Quiero reemplazar varias instancias de cadenas dentro de este archivo, e intenté usar PowerShell para hacer el trabajo.

Funciona bien para una única sustitución, pero hacer varias sustituciones es muy lento porque cada vez tiene que analizar todo el archivo de nuevo, y este archivo es muy grande. El script se ve así:

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

Quiero algo como esto, pero no sé cómo escribirlo:

 $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 

Una opción es encadenar las operaciones de -replace juntas. El ` al final de cada línea se escapa de la línea nueva, lo que hace que PowerShell continúe analizando la expresión en la siguiente línea:

 $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 

Otra opción sería asignar una variable intermedia:

 $x = $_ -replace 'something1', 'something1aa' $x = $x -replace 'something2', 'something2bb' ... $x 

Para hacer que la publicación de George Howarth funcione correctamente con más de un reemplazo, debe eliminar la interrupción, asignar la salida a una variable ($ línea) y luego generar la 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 

Asumiendo que solo puede tener un 'something1' o 'something2' , etc. por línea, puede usar una tabla de búsqueda:

 $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 

Si puede tener más de uno, simplemente elimine el break en la statement if .

Con la versión 3 de PowerShell, puede encadenar las llamadas de reemplazo juntas:

  (Get-Content $sourceFile) | ForEach-Object { $_.replace('something1', 'something1').replace('somethingElse1', 'somethingElse2') } | Set-Content $destinationFile 

Una tercera opción para un one-liner segmentado es anidar los reemplazos:

 PS> ("ABC" -replace "B","C") -replace "C","D" ADD 

Y:

 PS> ("ABC" -replace "C","D") -replace "B","C" ACD 

Esto preserva el orden de ejecución, es fácil de leer y se adapta perfectamente a una tubería. Prefiero usar paréntesis para control explícito, auto-documentación, etc. Funciona sin ellos, pero ¿en qué medida confías en eso?

-Replace es un operador de comparación, que acepta un objeto y devuelve un objeto presumiblemente modificado. Es por eso que puedes astackrlos o anidarlos como se muestra arriba.

Por favor mira:

 help about_operators