web-dev-qa-db-fra.com

Comment remplacer plusieurs chaînes dans un fichier à l'aide de PowerShell

J'écris un script pour personnaliser un fichier de configuration. Je souhaite remplacer plusieurs instances de chaînes dans ce fichier et j'ai essayé d'utiliser PowerShell pour effectuer le travail.

Cela fonctionne bien pour un seul remplacement, mais effectuer plusieurs remplacements est très lent car chaque fois, il doit analyser à nouveau le fichier entier, et ce fichier est très volumineux. Le script ressemble à ceci:

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

Je veux quelque chose comme ça, mais je ne sais pas l'écrire:

$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
93
Ivo Bosticky

Une option consiste à chaîner le -replace opérations ensemble. Le ` à la fin de chaque ligne échappe à la nouvelle ligne, ce qui permet à PowerShell de continuer à analyser l’expression de la ligne suivante:

$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

Une autre option serait d’attribuer une variable intermédiaire:

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

Pour que la publication de George Howarth fonctionne correctement avec plusieurs remplaçants, vous devez supprimer la rupture, affecter le résultat à une variable ($ line), puis générer la variable suivante:

$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
23
TroyBramley

Avec la version 3 de PowerShell, vous pouvez chaîner les appels de remplacement:

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

En supposant que vous ne pouvez avoir qu'un seul 'something1' ou 'something2', etc., par ligne, vous pouvez utiliser une table de correspondance:

$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 vous pouvez en avoir plusieurs, supprimez simplement break dans l'instruction if.

8
George Howarth

Une troisième option, pour une doublure en pipeline, consiste à imbriquer les remplacements:

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

Et:

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

Cela préserve l’ordre d’exécution, est facile à lire et s’intègre parfaitement dans un pipeline. Je préfère utiliser des parenthèses pour le contrôle explicite, l'auto-documentation, etc. Cela fonctionne sans elles, mais jusqu'à quel point avez-vous confiance en cela?

-Replace est un opérateur de comparaison qui accepte un objet et retourne un objet probablement modifié. C'est pourquoi vous pouvez les empiler ou les imbriquer comme indiqué ci-dessus.

S'il te plait regarde:

help about_operators
6
Haakon Dahl