美文网首页
VIM按照列合并行

VIM按照列合并行

作者: SpaceCat | 来源:发表于2021-12-22 23:19 被阅读0次

    之所以写这篇单独记下这个问题,是因为我觉得这篇里面读取全部文本行并逐行处理的技巧,是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,就可以实现前面效果的行合并。

    相关文章

      网友评论

          本文标题:VIM按照列合并行

          本文链接:https://www.haomeiwen.com/subject/yyicqrtx.html