2011-09-11 67 views
2

我有一段很长的文本,其中一些行需要稍后重复。替换Vim后面几行的第一个匹配模式

我把标签这样的文字:

{F1}text need to be repeated later{/F1} 

,所以我可以添加多个{F1}{/F1}到后面的章节,并把它们之间的第一行的内容。

的问题是,会有很多的标签,如这个喜欢{F2}{/F2}等...而这模式匹配所有这些太:

{\(.*\)}.*{\/\1} 

所以,我想搜索的不同每个第一次出现标签并将其替换为后续行,因此,当我更改第一行并再次替换时,所有行都会更新,也许会自动使用autocmd BufWrite

我怎么能这样做?我接受任何解决方案,不一定使用我用{}{/}标签标记第一行的想法。会有很多标签,我不想一个一个地用单个替代命令来完成。

我试图与此:

:g/{\(.*\)}\(.*\){\/\1}/s/{\1}.*{\/\1}/{\1}\2{\/\1}/ 

但它说:(根据其在描述

E65 Illegal back reference. 
+2

你能不能更好地发布示例文本(之前/之后),以便我们能更好地理解你确切想要做什么? – Benoit

+1

我可能是错的,但我认为错误来自在s ///的替换部分中使用反向引用,而不捕获匹配部分。 – johnny

回答

2

是下面列出的ReplicateTags()函数运行的取代 命令替换每个标签的内容 问题),在该标签的第一次出现时带有文本。替换 在整个缓冲区上运行,并在一次处理中处理所有标记 (接受多行非重叠标记)。该函数返回一个字典 ,将标签名称映射到其第一次出现的内容。

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

男人,这真棒! :D正是我想要的。 – kissgyorgy