Replace the very first matching pattern on later lines in Vim
I have a long text where some lines need to be repeated later.
I put tags like this in the text:
{F1}text need to be repeated later{/F1}
so I can add multiple {F1}{/F1}
to later sections and put the contents of the first line between them.
The problem is that there will be a lot of tags like this like {F2}{/F2}
etc... and this pattern matches all of 开发者_如何学Pythonthose too:
{\(.*\)}.*{\/\1}
So, I want to search every first occurrence of different tags and replace them on later lines, so when I change the first line and make a substitute again, all of the lines will updated, maybe automatically with an autocmd BufWrite
.
How could I do this? I accept any solution, not necessarily using my idea of marking the first lines with {}{/}
tags. There will be a lot of tags and I don't want to do it one-by-one with individual substitute commands.
I tried with this:
:g/{\(.*\)}\(.*\){\/\1}/s/{\1}.*{\/\1}/{\1}\2{\/\1}/
but it says:
E65 Illegal back reference.
The ReplicateTags()
function that is listed below runs a substitution
command replacing contents of each tag (according to its description in the
question) with text in the first occurrence of that tag. The substitution
operates on the whole buffer and processes all of the tags in one pass
(accepting multiline non-overlapping tags). The function returns a dictionary
that maps tag names to contents of their first occurrence.
function! ReplicateTags()
let dict = {}
%s/{\([^}]\+\)}\(\_.\{-}\){\/\1}/\=Tag(dict, submatch(1), submatch(2))/ge
return dict
endfunction
function! Tag(dict, tag, str)
let a:dict[a:tag] = get(a:dict, a:tag, a:str)
return printf('{%s}%s{/%s}', a:tag, a:dict[a:tag], a:tag)
endfunction
精彩评论