zoukankan      html  css  js  c++  java
  • Vim案例两则

    在博问中看见两个比较典型的Vim处理文本的案例,总结一下,希望对大家有所帮助。如果大家有好的方法,欢迎讨论。尤其是第二个案例,如果能够一个命令处理更好。

    案例一

    这是在博问中看到的一个问题,原始文本如下。

    要求处理成下面的样子,也就是把逗号从行尾移动到下一行第一个单词前面。

    我的第一想法是先将2-6行的逗号删除,然后在3-7行加上逗号即可。

    删除2-6行的逗号

    :%s/,// 

    解释一下:

    • : 冒号在Vim里面是命令引导符,想要输入命令必须先输入冒号。
    • % 表示匹配所有行
    • s/old/new/ 表示用new来替换old。s表示substitude(替换)。在s/,//中,old是逗号,new是空(注意后面两个斜线之间啥也没有,表示空)。

    在3-7行前面加上逗号

    :3,7s/\</,/

    解释一下:

    • 3, 7 表示对第3行至第七行进行处理,在Vim中m, n表示对第m到第n行进行处理,比如:1,10d表示删除1-10行
    • s/\</,/ 表示用逗号替换\<,<表示单词边界,属于特殊字符,需要转义,所以是\<

    这样就搞定了,但是转头一想,有没有更简单的办法呢?上面的办法虽然也很简单,但是需要两次命令才能完成,有没有办法用一个命令搞定呢。搞了一会,终于搞定,命令如下。

    :%s/,\n\(\s*\)/\r\1,/

    解释一下:

    • %s/old/new/ 表示对所有行中的old用new来替换,这里每一行只有一个逗号,所以不用加g,如果有多个逗号,那么要变成%s/old/new/g的形式,g表示对每行中的所有满足条件的文本进行替换。也就是说%是纵向的,而g是横向的。
    • ,\n\(\s*\) 匹配逗号,换行以及行首的若干空格。如下图                                                     
    • \r\1,匹配换行,行首的若干空格及逗号,这里\1是回溯引用,表示前面第一个括号对应的匹配,也就是行首的若干空格,因为添加逗号时不能破坏这些空格,所以匹配的时候进行保留以便替换时引用之。

    注意,上面的(和)属于特殊字符,需要转义,如果觉得\(\)这种方式难看,可以在表达式前面加上\v。如此则特殊字符无需再转义,可以像perl一样使用正则表达式了。

    :%s/\v,\n(\s*)/\r\1,/g

    案例二

    也来来自于博问,要求将只包含5个字符(字母,数字,或者下划线)的行,删除其行尾的换行符。

    原始文本如下:

    处理之后如下:可见2,3,4行的换行符都被删除了。

    我首先想到的命令是

    :g/\v^\w{5}$/ s/\n//g

    解释一下:

    整个表达式可以分成两个主要部分。:g/\v^\w{5}$/设为A,s/\n//g设为B。那么这个命令的含义就是对于满足条件A的行,执行命令B。也就是对于所有只包含5个字符的行,删除其行尾的换行符。

    • :g/patter/ g表示global,patter是一个正则表达式,这句话的意思是对于所有满足patter的行,用随后地命令(即s/\n//g)进行处理。
    • \v^\w{5}$ 表示只包含5个字符的行,\v表示后面的特殊字符不用转义,比如{}。^表示行首,$表示行尾。\w表示单词字符,即字母,数字或者下划线。
    • s/\n//g 表示用空替换\n,也就是删除换行符。

    但是非常遗憾的是,执行完这个命令后,结果并不正确,如下:

    可以看到,第二个abcde末尾的换行并没有删除掉,为什么会这样呢?仔细分析一下这个命令的执行步骤。

    首先Vim解析命令然后找到第一个满足条件的行abcde,并删除其末尾的换行符,此时文本变成下面的样子。

    这时,第二行文本是abcdeabcde,共10个字符,已经不再满足5个字符的条件了,所以Vim不会再删除其末尾的换行了,因而就产生了上面的错误结果。

    看来用一个命令处理有点困难,那就分成两个吧。虽然麻烦一点,但是结果正确。

    首先把要处理的行加上一个特殊标志,这个标志能够将待处理的行与其它行区别开来,所以要选择未在文本中出现的字符。另外一个要求是处理完之后这个标志也要删除,所以把它加在行尾,可以与换行符一并删除。

    先在包含5个字符的行末尾加上#

    :%s/\v(^\w{5}$)/\1#/g

    删除所有的#和换行符。

    :%s/#\n//g

    由于这次不再以字符个数来甄别处理的行,而是以#号来定位,即使两行合并之后,#号仍然存在,结果自然就正确了。你有更简单的办法么?

    参考

    关于跨行匹配,下面这个网页上有详细的介绍。

    Vim, Search across multiplelines

    作者:zdd
    出处:http://www.cnblogs.com/graphics/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    Java中BigDecimal的8种舍入模式
    Spring 4.3.2下实现http多次断点下载
    java文件同步性能测试
    JavaMail发送邮件时判断发送结果1.5.x
    关于mysql备份说明
    jxl 2.6.12 与 jxl 2.3.0 稳定版性能比较
    select选择框内容左右移动添加删除栏(升级)
    JS 清除字符串数组中,重复元素
    Js 数据容量单位转换(kb,mb,gb,tb)
    fine-uploader 5.11.8 (最新版) 使用感受
  • 原文地址:https://www.cnblogs.com/graphics/p/2995926.html
Copyright © 2011-2022 走看看