问题
I know I can use AWK but I am on a Windows box. I am making a function for others that may not have AWK. I also know I can write a C program but I would love not have to create maintain and compile something for a little Vim utility I am making.
The original file might be
THE DAY WAS LONG
THE WAY WAS FAST
and it would become
TT
HH
EE
DW
AA
YY
WW
AA
SS
LF
OA
NS
GT
UPDATE: Golf rules apply to selecting correct answer.
UPDATE: Python fans should check out Mr. Duffy's answer below.
回答1:
Here is a command in Vim language. So you don't have to compile Vim with +python support.
function! s:transpose()
let maxcol = 0
let lines = getline(1, line('$'))
for line in lines
let len = len(line)
if len > maxcol
let maxcol = len
endif
endfor
let newlines = []
for col in range(0, maxcol - 1)
let newline = ''
for line in lines
let line_with_extra_spaces = printf('%-'.maxcol.'s', line)
let newline .= line_with_extra_spaces[col]
endfor
call add(newlines, newline)
endfor
1,$"_d
call setline(1, newlines)
endfunction
command! TransposeBuffer call s:transpose()
Put this in newly created .vim file inside vim/plugin dir or put this to your [._]vimrc.
Execute :TransposeBuffer
to transpose current buffer
回答2:
Vim support for a number of scripting languages built in -- see the Python interface as an example.
Just modify vim.current.buffer
appropriately and you're set.
To be a little more specific:
function! Rotate()
python <<EOF
import vim, itertools
max_len = max((len(n) for n in vim.current.buffer))
vim.current.buffer[:] = [
''.join(n) for n in itertools.izip(
*( n + ' ' * (max_len - len(n))
for n in vim.current.buffer))]
EOF
endfunction
回答3:
If scripts don't do it for you, you could record the actions to a register (the carriage returns are added for readability):
qa
1G0
xGo<Esc>p
1G0j
xGp
q
This will give you a macro that you could run against the example above, or any 2-line strings of the same length. You only need to know the length of the string so you can iterate the operation the correct number of time
16@a
A fairly basic solution, but it works.
回答4:
The following function performs required editing operations to "transpose" the contents of the current buffer.
fu!T()
let[m,n,@s]=[0,line('$'),"lDG:pu\r``j@s"]
g/^/let m=max([m,col('$')])
exe'%norm!'.m."A \e".m.'|D'
sil1norm!@s
exe'%norm!'.n.'gJ'
endf
Below is its one-line version,
let[m,n,@s]=[0,line('$'),"lDG:pu\r``j@s"]|exe'g/^/let m=max([m,col("$")])'|exe'%norm!'.m."A \e".m.'|D'|exe'sil1norm!@s'|exe'%norm!'.n.'gJ'
回答5:
Charles Duffy's code could be shortened/improved using izip_longest
instead of izip
:
function! Rotate()
:py import vim, itertools
:py vim.current.buffer[:] = [''.join(c) for c in itertools.izip_longest(*vim.current.buffer, fillvalue=" ")]
endfunction
回答6:
I've developed a vim plugin to do it. You can find it here. Run :Transpose
to transpose the whole file.
来源:https://stackoverflow.com/questions/704130/can-i-transpose-a-file-in-vim