Pregunta 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

76
2017-08-04 06:48


origen


Respuestas:


Una opción es encadenar -replace operaciones juntas. los ` al final de cada línea se escapa de la nueva línea, 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

122
2017-08-04 07:10



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

21
2018-02-17 10:42



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

8
2018-01-10 11:54



Asumiendo que solo puedes tener uno '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 break en el if declaración.


7
2017-08-04 07:20



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 apilarlos o anidarlos como se muestra arriba.

Por favor mira:

help about_operators

5
2018-01-04 04:38