powershellfull-text-searchtext-filesstring-operations

powershell import data from text file after string


There seems to be questions that are similar floating around on the web although the answers vary and i just cannot get the outcome i am looking for.

Below simply appends the content within the txt file at the end of the file

Add-Content -Path "HeartBeat.txt" -Value (Get-Content "insertme.txt")

although i want to using powershell to find a string in a text file and then copy the contents from another text file after this found string.

Factitious example of a text file searching for string "HeartBeat"

<xml>
<Server>
  <HeartBeat>1</HeartBeat>
</Server>

There is another text file called "insertme.txt" that will insert its contents on a new line after "HeartBeat"

<dummydata>
<port></port>
<ipaddress></ipaddress>

Once appended will be

<xml>
<Server>
  <HeartBeat>1</HeartBeat>
  <dummydata>
  <port></port>
  <ipaddress></ipaddress>
</Server>

Any help would be appreciated.

Thank you


Solution

  • If you want a truly robust solution, use XML processing, which PowerShell supports via the [xml](System.Xml.XmlDocument) .NET type.

    If you still want a purely text-based solution, try the following (PSv3+; reads both files into memory in full; I'm using a LF-only newline ("`n") in the code; replace it with "`r`n" if you want CRLF newlines):

    (Get-Content -Raw Heartbeat.txt) -replace
      '(?m)^.*<HeartBeat>.*$',
      ('$&' + "`n" + (Get-Content -Raw InsertMe.txt).TrimEnd() -replace '(?m)^', '  '))|
        Set-Content HeartBeat.txt # PSv5+: Add -NoNewline to avoid extra newline
    

    Note: The only reason that it is possible to both read from Heartbeat.txt and write back to it in a single pipeline is that its content is read into memory up-front, in full, due to the (...) around the Get-Content command.
    While this approach is convenient, it also bears a slight risk of data loss, which can occur if the pipeline is interrupted before all content has been written back to the file.


    If you want to modify the insertion to apply a fixed indentation to each line of the inserted content:

    (Get-Content -Raw Heartbeat.txt) -replace
      '(?m)^.*<HeartBeat>.*$',
      ('$&' + "`n" + (Get-Content -Raw InsertMe.txt).TrimEnd() -replace '(?m)^', '  '))|
        Set-Content HeartBeat.txt # PSv5+: Add -NoNewline to avoid extra newline