Заменить самый первый соответствующий шаблон на более поздних строках в Vim - PullRequest
2 голосов
/ 11 сентября 2011

У меня длинный текст, где некоторые строки нужно повторить позже.

Я поместил теги, подобные этому, в тексте:

{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.

1 Ответ

2 голосов
/ 11 сентября 2011

Функция 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
...