If I paste the output of :ls into a buffer, the command
:%s/.*\(\".*\"\).*/\1/
reduces that output to just the file paths. Wanting to achieve that result in a variable, I did
:redir => x|silent :ls|redir END
:let y = substitute(x, ".*\(\".*\"\).*", "\1", "g")
which accomplished absolutely nothing, y is identical to x. I've tried umpteen variations on that substitute command, getting only the same result, or a bunch of error messages. How s开发者_运维技巧hould I be specifying it?
You need to escape backslashes in quotes. Use \\(
and \\\"
with substitute()
.
You have two errors: first was already mentioned by @Radu, second is arises from the fact that in substitute()
newline matches .
, while in :s
it is not. That is why «only the final match is delivered». I can post a correct solution using :redir
, :ls
and substitute()
, but instead suggest the following:
let buflist=map(filter(range(1, bufnr('$')), 'buflisted(v:val)'), 'bufname(v:val)')
If you want output almost identical to what :ls
has, try replacing bufname(v:val)
with 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
The above command leaves you with a list of strings. If you want to have a newline-separated «list» instead, use
let bufliststr=join(buflist, "\n")
If you still want to use substitute()
, see :h /[]
.
The variable x contains
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
By my reading of :h /[], particularly "...Without the "_" or "\n" the collection does not match an end-of-line...", then
:let y = ""
:let y = substitute(x, '[.]*\("[.]*"\)[.]*', '\1', "g")
should have done the job. But it delivered
"junk"
just as it did without the []. I then tried
:let y = ""
:let y = substitute(x, '[^\n]*\("[^\n]*"\)[^\n]*', '\1', "g")
and got exactly the same result.
Clearly vim does not use the actual newline character internally, neither for variables nor for registers. So it treats a variable as a single line. Which led me to this solution
:let y = substitute(x, '[^"]*\("[^"]\+"\)[^"]*', ':tabe \1\n', 'g')
yielding y containing
:tabe "~/Session.vim"
:tabe "~/.vimrc"
:tabe ".vim/vscripts/makesess.vim"
:tabe "~/Documents/vimcht"
:tabe "~/.fluxbox/startup"
:tabe "~/Documents/Notes"
:tabe "~/Documents/bashcht"
:tabe "junk"
as desired to form my Session.vim file
精彩评论