Frage So ersetzen Sie mehrere Zeichenfolgen in einer Datei mithilfe von PowerShell


Ich schreibe ein Skript zum Anpassen einer Konfigurationsdatei. Ich möchte mehrere Instanzen von Zeichenfolgen innerhalb dieser Datei ersetzen, und ich habe versucht, PowerShell zu verwenden, um die Aufgabe auszuführen.

Es funktioniert gut für eine einzelne Ersetzung, aber mehrere Ersetzungen durchzuführen ist sehr langsam, weil jedes Mal die gesamte Datei erneut analysiert werden muss, und diese Datei ist sehr groß. Das Skript sieht so aus:

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

Ich möchte so etwas, aber ich weiß nicht, wie ich es schreiben soll:

$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


Ursprung


Antworten:


Eine Möglichkeit ist die Verkettung der -replace Operationen zusammen. Das ` Am Ende jeder Zeile wird der Zeilenumbruch entfernt, wodurch PowerShell den Ausdruck in der nächsten Zeile weiter analysiert:

$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

Eine andere Option wäre, eine Zwischenvariable zuzuweisen:

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

122
2017-08-04 07:10



Um den Beitrag von George Howarth zu erhalten, der richtig mit mehr als einem Ersatz arbeitet, müssen Sie den Bruch entfernen, die Ausgabe einer Variablen ($ line) zuweisen und dann die Variable ausgeben:

$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



Mit Version 3 von PowerShell können Sie die Replace-Aufrufe zusammenketten:

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

8
2018-01-10 11:54



Angenommen, Sie können nur einen haben 'something1' oder 'something2'usw. pro Zeile können Sie eine Nachschlagetabelle verwenden:

$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

Wenn Sie mehrere davon haben können, entfernen Sie einfach die break in dem if Erklärung.


7
2017-08-04 07:20



Eine dritte Option, für einen Pipeline-One-Liner, ist die Verschachtelung der -replaces:

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

Und:

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

Dies bewahrt die Ausführungsreihenfolge, ist leicht zu lesen und fügt sich nahtlos in eine Pipeline ein. Ich bevorzuge Klammern zur expliziten Kontrolle, zur Selbstdokumentation usw. Es funktioniert ohne sie, aber wie weit vertrauen Sie das?

-Replace ist ein Vergleichsoperator, der ein Objekt akzeptiert und ein vermutlich modifiziertes Objekt zurückgibt. Aus diesem Grund können Sie sie wie oben gezeigt stapeln oder verschachteln.

Bitte sehen Sie:

help about_operators

5
2018-01-04 04:38