Reputation: 8747
Suppose I have 5 lines of text, if I input some commands to let vim process each line, Vim will process the text one by one, first line, second line, ... the last line. what I want is to let Vim process my text in reverse order. that is the last line first, then the 4th line, and at last the first line.
Why I need this? I have the following text
1234567890
abc
123
def
1234567890
123456789
I want to remove the newline symbol(\n) from lines which contains 3 characters. so after processing,I will get the following text
1234567890
abc123def1234567890
123456789
It seems a piece of cake, I use the following command
:%s/\v(^\w{3})\n/\1/
But what i got is
1234567890
abc123
def1234567890
1234567890
Why? I guess vim first remove \n from the second line, then this line has text abc123, now vim will not remove \n after 123, since it's not 3 characters now, so vim process the next line def, and remove \n from it, that's the result i got.
If vim can process from back to front, this will not happen and I can got the result I want.
BTW, I can get the expected result in other ways, I just want to know whether this is possible.
Upvotes: 2
Views: 125
Reputation: 195229
this line should do what you want:
:%s/\v(\_^\w{3}\n)+/\=substitute(submatch(0),"\n","","g")/
if you want to do it simpler with external command, e.g. awk, you could:
%!awk '{printf "\%s", length($0)==3? $0:$0"\n"}'
Upvotes: 1
Reputation: 15735
In this case it is easier to use the :global
command to join the lines.
:g/^\w\{3}$/normal! gJ
The command gJ
joins the current line with the following line without inserting any spaces. The global command above calls gJ
on each line containing only three characters. It works by marking all the matches first, before performing the operation, so the problem of looping is avoided.
Upvotes: 1
Reputation: 172738
Explicitly loop over the range of lines (e.g. the visually selected ones) backwards, then execute the command on each line. I've used :join
here instead of the :substitute
with a newline:
:for i in range(line("'>"), line("'<"), -1)| silent execute i . 'g/^\w\{3}$/join!' | endfor
Upvotes: 2
Reputation: 123608
Can be achieved using perl:
while (<>) {
chomp if (/^...$/);
print;
}
Upvotes: 2