开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜