powershellcontrol-characters

How to replace multiple lines from a text file using Powershell -replace


I am writing a script changing the memory value within a configuration file. I want to search for a set specific set of lines within this file, and I tried using PowerShell to do the job.

It works fine for a single line replace, but trying to match across multiple lines does not produce results. The script is as follows

A section of the config that I am trying to parse is below:

    {
      "taskType": "BuildDynamicMPLSCloud",
      "version": 1,
      "subTasks": [],
      "execName": "BuildDynamicMPLSCloud",
      "execCategory": 1
      "maximumMemory": 4294967296
    },
    {
      "taskType": "BuildDynamicMap",
      "version": 1,
      "subTasks": [],
      "execName": "BuildDynamicMap",
      "execCategory": 1,
      "maximumMemory": 4294967296
    },

Testing against one line to find and replace works:

$NewContent=Get-Content "C:\Program Files\NetBrain\Worker Server\conf\rmworker.json"  | ForEach-Object { $_-replace """maximumMemory"": 4294967296", """execName"": ""BuildDynamicMap"",`r`n`t  ""execCategory"": 1,`r`n`t  ""maximumMemory"":  8589934592" }

Set-Content -Path "C:\Program Files\NetBrain\Worker Server\conf\rmworker.json" -Value $NewContent

The output from above code is as shown below:

  {
      "taskType": "BuildDynamicMPLSCloud",
      "version": 1,
      "subTasks": [],
      "execName": "BuildDynamicMPLSCloud",
      "execCategory": 1
      "execName": "BuildDynamicMap",
      "execCategory": 1,
      "maximumMemory": 8589934592
    },
    {
      "taskType": "BuildDynamicMap",
      "version": 1,
      "subTasks": [],
      "execName": "BuildDynamicMap",
      "execCategory": 1,
      "execName": "BuildDynamicMap",
      "execCategory": 1,
      "maximumMemory": 8589934592
    },

But when attempting to match multiple lines for the same replace script does not succeed:

$NewContent=Get-Content "C:\Program Files\NetBrain\Worker Server\conf\rmworker.json"  | ForEach-Object { $_-replace """execName"": ""BuildDynamicMap"",`r`n`t  ""execCategory"": 1,`r`n`t  ""maximumMemory"":  4294967296" , """execName"": ""BuildDynamicMap"",`r`n`t  ""execCategory"": 1,`r`n`t  ""maximumMemory"":  8589934592" }


Set-Content -Path "C:\Program Files\NetBrain\Worker Server\conf\rmworker.json" -Value $NewContent

At the start of each newline there is 1 tab and 2 spaces within the config file.


Solution

  • If you want to use -Replace the following will work:

    $NewContent = (Get-Content "C:\Program Files\NetBrain\Worker Server\conf\rmworker.json" -Raw) -replace "(?ms)""execName"": ""BuildDynamicMap"",.*?""execCategory"": 1,.*?""maximumMemory"": 4294967296" , """execName"": ""BuildDynamicMap"",`r`n`t""execCategory"": 1,`r`n`t""maximumMemory"": 8589934592"
    

    I used the -Raw switch to return the file contents as one string. This removes the need to treat each line individually with a Foreach-Object command. In the regex part of the replace, I removed the linefeed and tab items in favor of .*?. I used the singleline and multiline modifiers (?sm) because the string is multiple lines and I want the . regex character to match new line characters. Your regex string also had an extra space after the "maximumMemory": that I removed.

    I left your replacement string as is, which will have an issue with spacing. You'll notice the extra two space indention. You may not want to use tab in your replacement or fix the other lines to align to tab.