Search code examples
powershellreplacelinesbetween

powershell replace text between 2 lines


I have a text file and want to replace the text between 2 lines. This is working OK until there is no text between the two lines.

my code:

$File = "D:\test.txt" 
$NewLine = "newline with some text"
$text = Get-Content "D:\test.txt" -raw

$text -replace ('(?m)(.*)^Line 3[\r\n]+Line 4([\r\n])', $NewLine) | 
  Out-File $File -Force

Text files:

Text file that does work:

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6


Text file that does NOT work:

Line 1
Line 2
Line 3
Some text here
Line 4
Line 5
Line 6

What I am doing wrong?


Solution

  • The issue you have is that your Regular Expression (RegEx for short) does not allow for anything between Line 3 and Line 4. Here's what you're using (cleaned up a tiny bit):

    (?m)^Line 3[\r\n]+Line 4[\r\n]
    

    Let us break that down just a little bit. (?m) puts the RegEx engine into multi-line mode, so it will allow you to use the carat ^ to indicate the beginning of a line, instead of just the beginning of the string. There's other things it does, but that's what you are using it for. I discarded the (.*), because it is pointless. So you have a carat indicating the beginning of a line, followed by the text Line 3, and then [\r\n]+ which will find the end of the line. Then it finds Line 4, immediately followed by the end of that line. This is why it fails when there is text, you didn't allow for any additional text. To do that you can use .*?. What that means is this: The dot indicates any character, doesn't matter if it's letter, number, symbol, or even a character that doesn't register on the screen. The asterisk * indicates that there needs to be zero or more of that, so zero or more of any character. The question mark tells it to look for zero or more, but to match as few characters as possible before moving on in the pattern, so it will only match things until it can move on to Line 4[\r\n]. The functional pattern would be:

    (?m)^Line 3[\r\n]+.*?[\r\n]Line 4[\r\n]