Vim regex: add line above all lines not starting with "#"

163 views Asked by At

I have a text file with a structure like this:

The quick  
#a comment
brown 
fox jumps  
#another comment
over  
the 
lazy
#yet another comment
dog

So each line either contains "normal" text or a comment starting with "#". I want this text to be replaced using regex, so that each "text"-line gets a comment line above it. The result should be something like:

#auto comment
The quick  
#a comment
brown 
#auto comment
fox jumps  
#another comment
over  
#auto comment
the 
#auto comment
lazy
#yet another comment
dog

However, I'm not able to create a working regex although I spent really much time. There's always at least one special case where my regex fails. The best one I was able to create is:

:%s/^\([^#].*\)\n\([^#].*\)$/\1\r#auto comment\r\2/g

This one works perfectly fine (except for the first line), if I run it twice. But running it only once skips some lines, e.g. I get this result:

The quick
#a comment
brown
#auto comment
fox jumps
#another comment
over
#auto comment
the
lazy
#yet another comment
dog

Notice that there's no line inserted between "the" and "lazy". The reason for this is, that the term "the" is a part of the regex group and part of the replaced text and so it won't be parsed by regex again.

Is there any possibility (well I bet there is and I'm just not able to find it...) to solve this issue? I realize that checking the first line is another problem, too. It would be great if this could be recognized, too, however this is currently not my main focus of attention.

3

There are 3 answers

1
Peter Rincker On BEST ANSWER

You can use a negative look-behind, \@<!, to ensure the previous line is not a comment.

%s/\(^#.*\n\)\@<!\_^[^#]/#auto comment\r&

For more information see:

:h /\@<!
:h /\_^
:h s/\\&
3
vks On
([^#\n]+\n#[\w ]+?\n[^\n]+(?:\n|$))|^([^\n]+\n)

Try this.Replace by #auto comment\n$1$2.See demo.

http://regex101.com/r/lZ5mN8/24

3
rottweilers_anonymous On

Use: :%s/^\([^#].*\)/#auto comment\r\1/g

Then run: :%s/^\(#.*\)\n#.*/\1/g

OR :%s/^\([^#].*\)/#auto comment\r\1/g | %s/^\(#.*\)\n#.*/\1/g