0
votes

I am trying to do two things. Firstly I am to remove all text after match, and secondly replace match line with new text.

In my example below I want to find the line List of animals and replace all lines following it in all documents *.txt with the text found in replaceWithThis.txt.

My first foreach below will remove everything that follows List of animals and my second foreach will replace List of animals and thus also adding new content following that line by content from replaceWithThis.txt.

replaceWithThis.txt contains:

List of animals
Cat 5
Lion 3
Bird 2

*.txt contains:

List of cities
London 2
New York 3
Beijing 6

List of car brands
Volvo 2
BMW 3
Audi 5

List of animals
Cat 1
Dog 3
Bird 7

Code:

$replaceWithThis = Get-Content c:\temp\replaceWithThis.txt -Raw

$allFiles = Get-ChildItem "c:\temp" -recurse | where {$_.extension -eq ".txt"}
$line = Get-Content c:\temp\*.txt | Select-String cLuxPlayer_SaveData | Select-Object -ExpandProperty Line
foreach ($file in $allFiles)
{
    (Get-Content $file.PSPath) |
    ForEach-object { $_.Substring(15,  $_.lastIndexOf('List of animals')) } |
    Set-Content $file.PSPath
}

foreach ($file in $allFiles)
{
    (Get-Content $file.PSPath) |
    Foreach-Object { $_ -replace $line,$replaceWithThis } |
    Set-Content $file.PSPath
}

Final result in all (*.txt) should be:

List of cities
London 2
New York 3
Beijing 6

List of car brands
Volvo 2
BMW 3
Audi 5

List of animals
Cat 5
Lion 3
Bird 2
1

1 Answers

2
votes

Using Regular Expression, the below code should work:

$filesPath       = 'c:\temp'
$replaceFile     = 'c:\temp\replaceWithThis.txt'
$regexToFind     = '(?sm)(List of animals(?:(?!List).)*)'
$replaceWithThis = (Get-Content -Path $replaceFile -Raw).Trim()

Get-ChildItem -Path $filesPath -Filter *.txt | ForEach-Object {
    $content = $_ | Get-Content -Raw
    if ($content -match $regexToFind) {
        Write-Host "Replacing text in file '$($_.FullName)'"
        $_ | Set-Content -Value ($content -replace $matches[1].Trim(), $replaceWithThis) -Force
    }
}

Regex Details

(                      Match the regular expression below and capture its match into backreference number 1
   List of animals     Match the characters “List of animals” literally
   (?:                 Match the regular expression below
      (?!              Assert that it is impossible to match the regex below starting at this position (negative lookahead)
         List          Match the characters “List” literally
      )
      .                Match any single character
   )*                  Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
)