Reputation: 549
I would like to find a good way in Vim to do this search and replace for the following -
name_1
end
name_2
end
name_3
end
where I take name_"x" and append it to it's following "end" statement. So it would look like this -
name_1
end_name_1
name_2
end_name_2
name_3
end_name_3
Note - the empty line before name_3 ruins a constant line spacing between "name_x" and "end". So I was thinking of something like
:g/\(name_x\)/,/end/ s/end/end_\1/
Now that doesn't work trying to store the first pattern like that but hopefully you get the idea. Any tricks here?
Thanks
Upvotes: 0
Views: 327
Reputation: 378
A regex based solution is:
:%s/\(name.*\)\(\n\+.*\)/\1\2_\1
This group every line which contains name
followed by anything, another group which could have any number of return
followed bay anything, then append first group to the second one.
Upvotes: 0
Reputation: 45177
The issue you are having is that \1
refers to the current substitution's match group not the :g
command's pattern. Sadly you can not access previous match groups from previous searches. There are however ways to accomplish your goal. The first I would suggest is a macro.
First off start on a a non matching line. This can be done by inserting a blank line at the top of the file if needed (just remove it afterwards).
/name_\d\+
y//e
/end/e
a_
p
q
999@q
Here is the macro I used:
:let @q = "/name_\\d\\+\<cr>y//e\<cr>/end/e\<cr>a_\<esc>p"
The other way is to use the :global
command in a similar fashion to your attempt.
:g/name_\d\+/let @@=matchstr(getline('.'),'name_\d\+')|/end/s//\=submatch(0).'_'.@@/
I personally this is much too complicated, but it is nice to have options. The command can be broken down into the following parts:
:g/name_\d\+
execute a command on each line matching name_ and some numbergetline('.')
will return a string of the current linematchstr(getline('.'), 'name_\d\+')
will return only the matching part of the current linelet @@ = matchstr(...)
will set the matched portion to the default register/end/s/
will execute a :s
on the following line that matches end
s//\=.../
matches the last used pattern and replaces it with an express.submatch(0).'_'.@@
create a string with the whole matched pattern followed by an underscore and the contents of the unnamed register.For more information on the following topics see:
:h q
:h search-offset
:h :g
:h :let-@
:h registers
:h matchstr(
:h getline(
:h range
:h submatch(
Upvotes: 3