How to replace a multi line code with sed?

21,185

Solution 1

Perl to the rescue:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ will edit the file "in place", leaving a backup copy
  • -0777 reads the whole file at once, not line by line

The substitution s/// works similarly as in sed (i.e. it matches text = " followed by anything but double quotes many times up to a double quote), but in this case, it works on the whole file.

Solution 2

You have to check the pattern space and keep pulling in the Next line if it doesn't match e.g.

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

with gnu sed you can write it as

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

That's not very efficient though, better just select the range /text = "/,/"/, modify the first line and delete the rest:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

again, with gnu sed you can write it as a one-liner:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

Solution 3

Personally, I would do this in Perl. If we can assume that there are no " before the closing ", you can do:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

The -0 slurps the entire file, reading it into memory. The -p means "print every line (here, a "line" will be the entire file) after applying the script given by -e". The script itself is a simple substitution operator. It will capture the string text followed by 0 or more whitespace characters, an = and 0 or more whitespace again (text\s*=\s*) and save it as $1. Then, it will replace the captured pattern as well as the shortest quoted string it finds with the pattern ($1) and "". The s flag makes . match newlines.

Share:
21,185

Related videos on Youtube

blade19899
Author by

blade19899

I'm currently a Linux Engineer, that spends some time on AU, because Ubuntu 10.10, Maverick Meerkat, won me over. I have been an Ubuntu user even after the rise, and fall, of the Unity Desktop Interface. "You can teach a student a lesson for a day; but if you can teach him to learn by creating curiosity, he will continue the learning process as long as he lives." - Clay P. Bedford What little spare time I have, I spend on writing code in PHP.

Updated on September 18, 2022

Comments

  • blade19899
    blade19899 over 1 year

    I have a large file which has special characters in it. There is a multi line code there, that I want to replace with sed.

    This:

      text = "\
        ------                                                           ------\n\n\
        This message was automatically generated by email software\n\
        The delivery of your message has not been affected.\n\n\
        ------                                                           ------\n\n"
    

    Needs to turn into this:

    text = ""
    

    I tried the following code, but no luck:

    sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf
    

    It does not replace anything and does not display any error messages

    I have been playing with it, but everything I try does not work.

    • terdon
      terdon about 8 years
      Does it need to be sed or are you open to other tools? Can there be " inside the text= block? Can there be other cases of text = in your file? Will there always be 4 lines of text or can there be more/less?
    • blade19899
      blade19899 about 8 years
      Preferably sed, or anything that does not require installation in a CentOS server. Out of the box tools
    • blade19899
      blade19899 about 8 years
      @terdon There are not other text = in the folder, the out come needs to be text = "". The files has 891 lines of code. SO, it needs te respect the other text.
    • joH1
      joH1 about 8 years
      do you want to overwrite the file or just modify the output?
    • blade19899
      blade19899 about 8 years
      @Moonstroke NO OVERWRITE. It just needs to replace the text - as seen in my question - to text = "". As seen in my question.
  • Angel Todorov
    Angel Todorov about 8 years
    correction, -00 reads in paragraphs, not the whole file (ref). If the text in quotes contains a blank line, then the regex will not match.
  • terdon
    terdon about 8 years
    @glennjackman argh! I always get those mixed up.. Which is why I actually double checked by adding an extra paragraph and running perl -00ne 'print;exit'. And I still put the wrong one in my answer! Thanks, fixed now.