Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
    
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 at 12:42
    
Preferably sed, or anything that does not require installation in a CentOS server. Out of the box tools – blade19899 Feb 19 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 at 12:45
    
do you want to overwrite the file or just modify the output? – Moonstroke Feb 19 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 at 12:47
up vote 6 down vote accepted

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.

share|improve this answer
    
+1 for being the first, and that it actually worked. – blade19899 Feb 19 at 12:53

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
share|improve this answer

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|improve this answer
    
+1 This worked also. – blade19899 Feb 19 at 12:54
    
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 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 at 22:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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