8

I've seen multiple answers to delete a single line with sed or grep, but I'm in need to search for a line, delete that one, and the 2 proceeding lines. For example, in the file ~/.profile I have lines like:

#Set environment variable
export NAME=value
# (blank line here)

So I'd like to search for #Set environment variable, and delete it, then delete the next line export NAME=variable (content shouldn't matter), and the following blank line. The export variable names are dynamic, but the comment will always be the same. There could be other export variables without the above comment which I do not want to delete.

How can I accomplish this?

3 Answers 3

6

With the newer version of GNU sed (comes with Ubuntu), you can match the newlines literally:

sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt
  • -z option will treat the lines of input files as terminated by ASCII NUL rather than newline, thus we can use \n to match the new lines

  • #Set environment variable\n will match the first line (with new line)

  • export [^\n]\+\n will match the second line starting with export

  • As the third line is blank simply \n will do

  • Then we replace the whole pattern matched with blank to keep the desired portion

In you want to overwrite the file with the modified content:

sed -zi.bak 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt

The original file will be retained as file.txt.bak, if you don't want that just use sed -zi.

Here is a test:

$ cat file.txt 
#Set environment variable
export NAME=value
#some text

#Set environment variable
export NAME=value

check
value

export some=value

#Set environment variable
export NAME=value

foo bar



$ sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt 
#Set environment variable
export NAME=value
#some text

check
value

export some=value

foo bar
2

It is very easy to do this with standard sed's delete command:

cp ~/.profile ~/.profile.bak
sed '/#Set environment variable/,+2 d' <~/.profile.bak >~/.profile

Be careful with your ~/.profile

2
  • this is not right....it will blindly remove the next two lines after match regardless of the contents....also you can just use sed -i instead of taking a backup beforehand..
    – heemayl
    Jun 17, 2015 at 17:05
  • 1
    @heemayl : but original post said "(content shouldn't matter)", at least for the "export" line. You might be right with the blank line, though.
    – ludvik02
    Jun 17, 2015 at 17:10
0

Although your question makes it look like you're looking for a command-line way to do this, if I were in your situation and only wanted to do this for one or two files, I would use emacs.

emacs has the capability of learning a sequence of keystrokes and then repeating them as many times as you want. So in your case I would open ~/.profile in emacs and then type

C-x ( C-s #Set environment variable C-a C-k C-k C-k C-x )

[which, in words, does this: C-x ( means "start learning this"; C-s means "search for", so then we search for #Set environment variable, and then C-a means "back to the beginning of the line, and the three C-k's mean "delete this line", and finally C-x ) means "stop learning this".]

After those commands have been typed once, emacs has deleted three lines, but it has also learnt how to do it by heart, so you can now type

C-x e

and it will do it again, or

C-u 100 C-x e

and it will do it 100 times (or stop when it can't find any more lines with "#Set environment variable" in).

The advantage of using emacs is that you can see your edits happening "live", and for a paranoid person like me who is scared that one sed typo can delete lots of stuff that I didn't want deleted, this makes me much happier [the moment things go wrong in emacs you can just go backwards and fix them with C-_].

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .