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.
Get-Content -Raw
reads a file into memory in full, as a single string.
Regex '(?m)^.*<HeartBeat>.*$'
matches a single line that contains substring <HeartBeat>
(note that the -replace
operator generally looks for multiple matches)
Replacement expression '$&' + "`n" + (Get-Content -Raw InsertMe.txt).TrimEnd()
replaces the matched line with itself ($&
), followed by a newline and the content of file InsertMe.txt
.
.TrimEnd()
is used to remove trailing newlines (and whitespace in general) so that insertion does not vary based on whether the file happens to end in a newline or not.
If you want to avoid an extra newline at the end of the updated file,
use Set-Content -NoNewline
, but note that this requires PSv5+.
In earlier versions you could apply .TrimEnd()
to the entire expression before sending it to Set-Content
.
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