之所以写这篇单独记下这个问题,是因为我觉得这篇里面读取全部文本行并逐行处理的技巧,是VIM高手和一般用户的分水岭。也就是说,这篇是一条vim的金线。
1、场景说明
这里要处理的文本有很多行,每行中有两列,列之间用\t
分隔如下:
asdf 1
asdf 1
qwer 3
qwer 3
qwer 3
qwer 3
qwer 3
asdf 1
asdf 1
qwer 3
qwer 3
qwer 3
qwer 3
我们想将第一列相同的行合并到一起,达到如下效果:
asdf 1, 1, 1, 1
qwer 3, 3, 3, 3, 3, 3, 3, 3, 3
2、解决方法
这里通过自定义一个vim命令来解决。在自定义命令中,调用了一个自定义的函数,如下:
" define a command to merge lines according to the first column
" every line has just two column split by \t
function! MergeLinesAsFirstColumn()
let dict = {}
let reslist = []
let @u = ''
g/$/let ln=getline(".") | let tmplist = split(ln, "\t") | if !has_key(dict, tmplist[0]) | let dict[tmplist[0]] = tmplist[1] | else | let dict[tmplist[0]] = dict[tmplist[0]] . ', ' . tmplist[1] | endif
for [k,v] in items(dict) | call add(reslist, k . "\t" . v) | endfor
let @u = join(reslist, "\n")
normal! ggdG
normal! 0"up
echo "Merge lines finished!"
return ''
endfunction
command MergeLinesAsFirstColumn exec MergeLinesAsFirstColumn()
将前面的行放到vimrc配置文件中,执行命令source $MYVIMRC
让配置生效,生效之后,在vim命令行执行:MergeLinesAsFirstColumn
,就可以实现前面效果的行合并。
3、分解和优化
前面这个版本是我在解决问题的时候,参照一个别的问题的脚本改出来的,可读性比较差。实际上,这里涉及的读取全部文本行并处理的技巧,适用的场景非常广泛。所以,这里对前面的版本进行了分解和优化,主要是提高了代码的可读性。如下:
" define a command to merge lines according to the first column
" every line has just two column split by \t
function! MergeLinesAsFirstColumn2()
" read all lines into a list
let allLines = []
g/$/let line=getline(".") | call add(allLines, line)
" Merging as the first column
let dict = {}
for l in allLines
let tmpList = split(l, "\t")
if !has_key(dict, tmpList[0])
let dict[tmpList[0]] = tmpList[1]
else
let dict[tmpList[0]] = dict[tmpList[0]] . ', ' . tmpList[1]
endif
endfor
" join the merge result into a result list, then to a register u
let resList = []
for [k,v] in items(dict)
call add(resList, k . "\t" . v)
endfor
let @u = join(resList, "\n")
normal! ggdG
normal! 0"up
"echo "Merge lines finished!"
return ''
endfunction
command MergeLinesAsFirstColumn2 exec MergeLinesAsFirstColumn2()
将前面的行放到vimrc配置文件中,执行命令source $MYVIMRC
让配置生效,生效之后,在vim命令行执行:MergeLinesAsFirstColumn2
,就可以实现前面效果的行合并。
网友评论