Search code examples
powershellcmdcygwintext-processing

Replacing lines between two specific strings - sed equivalent in cmd


I want to replace the lines between two strings [REPORT] and [TAGS]. File looks like this

Many lines 
many lines
they remain the same

[REPORT]

some text
some more text412

[TAGS]

text that I Want
to stay the same!!!

I used sed within :

sed -e '/[REPORT]/,/[TAGS]/c\[REPORT]\nmy text goes here\nAnd a new line down here\n[TAGS]' minput.txt > moutput.txt

which gave me this:

Many lines 
many lines
they remain the same

[REPORT]
my text goes here
And a new line down here
[TAGS]

text that I Want
to stay the same!!!

When I do this and open the output file in Notepad, it doesn't show the new lines. I assume that this is because of formatting issue a simple Dos2Unix should resolve the issue.

But because of this and also mainly due to the fact that not all of my colleagues have access to cygwin I was wondering if there's a way to do this in (or Powershell if there is no way to do a batch).

Eventually, I want to run this on number of files and change this section of them (between those two aforementioned words) to the text that I am providing.


Solution

  • Use PowerShell, present from Windows 7 on.

    ## Q:\Test\2018\10\30\SO_53073481.ps1
    ## defining variable with a here string
    $Text = @"
    Many lines 
    many lines
    they remain the same
    
    [REPORT]
    
    some text
    some more text412
    
    [TAGS]
    
    text that I Want
    to stay the same!!!
    "@
    
    $Text -Replace "(?sm)(?<=^\[REPORT\]`r?`n).*?(?=`r?`n\[TAGS\])",
                   "`nmy text goes here`nAnd a new line down here`n"
    

    The -replace regular expression uses nonconsuming lookarounds

    Sample output:

    Many lines
    many lines
    they remain the same
    
    [REPORT]
    
    my text goes here
    And a new line down here
    
    [TAGS]
    
    text that I Want
    to stay the same!!!
    

    To read text from file, replace and write back (even without storing in a var) you can use:

    (Get-Content ".\file.txt" -Raw) -Replace "(?sm)(?<=^\[REPORT\]`r?`n).*?(?=`r?`n\[TAGS\])",
                   "`nmy text goes here`nAnd a new line down here`n"|
    Set-Content ".\file.txt"
    

    The parentheses are neccessary to reuse the same file name in one pipe.