Vimscript: регулярное выражение работает в: s, но не в замещении () - PullRequest
3 голосов
/ 08 октября 2011

Если я вставлю вывод: ls в буфер, команда

:%s/.*\(\".*\"\).*/\1/

уменьшает этот вывод только до путей к файлам. Желая достичь этого результата в переменной, я сделал

:redir => x|silent :ls|redir END
:let y = substitute(x, ".*\(\".*\"\).*", "\1", "g")

, который абсолютно ничего не достиг, у идентичен х. Я пробовал множество вариантов этой команды замены, получая только один и тот же результат или кучу сообщений об ошибках. Как мне это указать?

Ответы [ 3 ]

5 голосов
/ 08 октября 2011

Вам нужно избегать обратной косой черты в кавычках.Используйте \\( и \\\" с substitute().

0 голосов
/ 09 октября 2011

Переменная x содержит

1 #    "~/Session.vim"                line 5
2      "~/.vimrc"                     line 34
3      ".vim/vscripts/makesess.vim"   line 4
4      "~/Documents/vimcht"           line 62
5      "~/.fluxbox/startup"           line 5
6      "~/Documents/Notes"            line 2604
7      "~/Documents/bashcht"          line 21
8 %a   "junk"                         line 10

По моему прочтению: h / [], в частности "... Без" _ "или" \ n "коллекция не соответствует концу строки ...", тогда

:let y = ""
:let y = substitute(x, '[.]*\("[.]*"\)[.]*', '\1', "g")

должен был сделать работу. Но это доставлено

"junk"

так же, как и без []. Я тогда попробовал

:let y = ""
:let y = substitute(x, '[^\n]*\("[^\n]*"\)[^\n]*', '\1', "g")

и получил точно такой же результат.

Очевидно, что vim не использует действительный символ новой строки внутри себя, ни для переменных, ни для регистров. Поэтому он рассматривает переменную как одну строку. Что привело меня к этому решению

:let y = substitute(x, '[^"]*\("[^"]\+"\)[^"]*', ':tabe \1\n', 'g')

с y

:tabe "~/Session.vim"
:tabe "~/.vimrc"
:tabe ".vim/vscripts/makesess.vim"
:tabe "~/Documents/vimcht"
:tabe "~/.fluxbox/startup"
:tabe "~/Documents/Notes"
:tabe "~/Documents/bashcht"
:tabe "junk"

по желанию для формирования моего файла Session.vim

0 голосов
/ 09 октября 2011

У вас есть две ошибки: первая была упомянута @Radu, вторая связана с тем, что в substitute() символ новой строки соответствует ., а в :s - нет.Именно поэтому «доставлен только финальный матч».Я могу опубликовать правильное решение, используя :redir, :ls и substitute(), но вместо этого предлагаю следующее:

let buflist=map(filter(range(1, bufnr('$')), 'buflisted(v:val)'), 'bufname(v:val)')

Если вы хотите, чтобы вывод, почти идентичный тому, который есть у :ls, попробуйте заменить bufname(v:val) с BufName(v:val):

function BufName(bnr)
    let bn=bufname(a:bnr)
    let bt=getbufvar(a:bnr, '&buftype')
    if empty(bn)
        return (empty(bt)?('[No Name]'):('[Scratch]'))
    elseif empty(bt)
        " This won't produce names like ../file, while :ls will "
        return fnamemodify(bn, ':~:.')
    elseif bt is# 'help'
        return fnamemodify(bn, ':t')
    else
        return bn
    endif
endfunction

Приведенная выше команда оставляет вам список строк.Если вы хотите вместо этого использовать разделенный новой строкой «список», используйте

let bufliststr=join(buflist, "\n")

Если вы все еще хотите использовать substitute(), см. :h /[].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...