4

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.

Cap10Br8KDance
  • 43
  • 1
  • 1
  • 5

1 Answers1

9

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.

AdminOfThings
  • 23,946
  • 4
  • 17
  • 27
  • Thanks for the great suggestion. this ended up working. I'm assuming (?ms) looks for start of the line and ".*?" allows any character prior to the next string correct? – Cap10Br8KDance May 17 '19 at 18:12
  • 1
    (?ms) is the multiline and single line modifiers. Single line allows `.` to match carriage returns and line feeds. Typically, it would not match those. The (?) syntax at the beginning of the regex sets the modifiers. Each modifier is represented by a single character. – AdminOfThings May 17 '19 at 18:32