How to replace a multi line code with sed?
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 N
ext 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.
Related videos on Youtube
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, 2022Comments
-
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 about 8 yearsDoes it need to be
sed
or are you open to other tools? Can there be"
inside thetext=
block? Can there be other cases oftext =
in your file? Will there always be 4 lines of text or can there be more/less? -
blade19899 about 8 yearsPreferably
sed
, or anything that does not require installation in a CentOS server. Out of the box tools -
blade19899 about 8 years@terdon There are not other
text =
in the folder, the out come needs to betext = ""
. The files has 891 lines of code. SO, it needs te respect the other text. -
joH1 about 8 yearsdo you want to overwrite the file or just modify the output?
-
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 about 8 yearscorrection,
-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 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.