9

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.

  • 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? – terdon Feb 19 '16 at 12:42
  • Preferably sed, or anything that does not require installation in a CentOS server. Out of the box tools – blade19899 Feb 19 '16 at 12:43
  • @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. – blade19899 Feb 19 '16 at 12:45
  • do you want to overwrite the file or just modify the output? – joH1 Feb 19 '16 at 12:45
  • @Moonstroke NO OVERWRITE. It just needs to replace the text - as seen in my question - to text = "". As seen in my question. – blade19899 Feb 19 '16 at 12:47
15

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.

5

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
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.

  • 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. – glenn jackman Feb 19 '16 at 22:35
  • @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. – terdon Feb 19 '16 at 22:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.