学习vi和vim编辑器(9):全局替换(2)

上一篇文章已经学习了如何通过vi编辑器中" :s "命令进行全局替换,而且可以在替换命令中使用正则表达式以进行强大的模式匹配。这一篇文章将学习模式匹配的更多范例,以进一步熟悉正则表达式。

模式匹配的范例:

(1)匹配一个完整的单词:如下图所示,如果需要将文本里所有的child单词替换成为children,可能最先想到的就是下图所示的替换命令:

技术分享

是这个命令会把childrendish,Fabrichild这两个单词中的child都做替换,这不是我们想要的。替换的关键就是child要是一个单独的单词,可能又想到如下的方法:

技术分享

该命令搜索以空格,逗号,分号结尾的child,并将该child替换为children,同时保留原来child之后的符号。但是该命令仍然会失败,因为Fabrichild也会被替换。

其实很简单,结合\< 和\>就能匹配出一个单独的完整的单词,如下命令就能完成我们想要的替换工作:

技术分享

(2)搜索一般的单词类:如下图所示,需要将mgibox,mgrbox,mgabox中的所有box替换成为square,可以采用如下方法:

技术分享

这个命令中所用到的特殊元字符都在上一篇文章中做了解释,这里就不再一一解释了。

(3)对文件路径做替换:如下图所示,需要将 /home/test/ 替换成为 /usr/local,由于" / "在替换命令中具有特殊含义(作为替换命令中各个部分的分隔符),所以需要按照如下方式来进行替换:

技术分享

但是上一篇文章中已经讲过,除了使用" / "作为分隔符,还可以使用其他字符作为分隔符,如下图所示,采用" ; "作为替换命令中各个部分的分隔符,可以使整个替换命令更简洁:

技术分享

(4)将第1至第10行之间的所有句号改为分号:" :1,10s/\./;/g ",因为" . "在替换字符串中具有特殊含义,所以需要通过" \ "转义字符将其转化为普通的句号。

(5)将出现的help或Help转化为HELP:" :%s/[hH]elp/\U&/g "。

(6)将一个或多个空格替换成一个空格:  :%s/  */ /g",注意搜索模式中"*"前面是两个空格,这样才能匹配出一个或多个空格。

(7)删除所有空白行:" :g/^$/d ","^$ "能够匹配出中间没有内容的行,即空白行。注意只包含空格或者tab键的行,虽然看上去是空白的,但是这个命令不会删除这样的行。如果需要删除空白行(不包含任何内容的行)和所有只包括空格或tab键的行,可以通过如下命令:" :g/^[ tab]*$/d "。

(8)删除每一行开头的所有空格:" :%s/^  *\(.*\)/\1/ ",注意第一个"*"前面有两个空格,这样才能匹配出一个或多个空格。
(9)删除每一行结尾的所有空格:" :%s/\(.*)\  *$/\1/",同样注意最后一个"*"前面有两个空格。

(10)在每一行的开头加上"//":通过在每行的开头加上"//",从而快速注释一段代码:

技术分享

注意以上命令采用" ; "作为分隔符,并且采用" . , +3"指定了注释的范围,即当前行及之后的3行代码。其实还有一种更简单的写法:

技术分享

这个命令将行开头(^)替换成为"//","^"代表一行的开头(这是一个逻辑上的概念,并不是实际的字符,因此实际的行首字符并不会真的被替换掉)。

(11)在文件所有行末尾都加上句号:" :%s/$/./ "。

(12)逆转所有用连字符分隔部分的顺序:

技术分享

(13)将文件中的每一个单词全变成大写:" :%s/.*/\U&/ " 或者 " :%s/./\U&/g ",但是第一个命令会更快一些。

(14)逆转文件中的各行顺序:" :g/.*/mo 0 "。该命令会按照文件行的顺序,依次将每一行移动到文件的开头,从而完成文件行顺序的逆转。其中" .* "会匹配出完整的一行,mo是ex编辑器中的移动命令,可以参考《学习vi和vim编辑器(6):ex编辑器概述(1)》或者也可以使用 " :g/^/mo 0 "。

(15)在所有不包含line单词的行的末尾加上 end: " :g!/line/s/$/end/ "。要想影响除了匹配模式以外的所有行,可以直接在g命令后面加上感叹号,或者直接使用v命令,因此如下命令也可以实现: " :v/line/s/$/end/ "。

(16)将每行开头的数字删除:

技术分享

用模式移动文本块:

正如之前所看到的,":g"命令可以和":d","mo",“co”等ex命令结合起来使用。同时可以使用模式作为分界的文本块。如下图所示,将 chapter one 的文件内容移动到文件末尾:

技术分享

该命令搜索chapter one所在的行(即第一章的标题行),并将该行及chapter two所在行的上一行之间的所有行(从而标记出了整个第一章的文本块)移动到文件末尾。

模式匹配最后的叮咛:

(1)匹配任意数量的任意字符串时,正则表达式总是尽可能地匹配出最多的文本;

(2)当我们重新思考一个匹配模式时,通常比较好的方法是更精准地修改变量(元字符),而不是用特定的文字来限制模式。在模式中运用越多变量,命令的力量就越强大;

 (3)有时精确地指定理想结果比起指定不要的结果困难的多。

用:g重复命令:

g命令可以选择某些行,但是伴随着的编辑命令却不一定要要影响这些选择的行。如下图所示,该命令能够将文件的第11到第12行复制到文件末尾,并重复10次这样的复制行为。

技术分享

解释一下该命令的工作行为:"1,10g"代表将在文件的第1至第10行执行搜索行为,由于搜索模式只是一个"^",所以每一行都符合搜索模式。当选中第一行时,执行后面的编辑命令,将文件的第11至第12行复制到文件结尾(该编辑命令与当前选中的第一行没有关系),接着选中第二行时,再次执行后面的编辑命令,因此将总共执行10次编辑命令,从而达到用:g来重复命令的效果。

收集行:

如下图所示,在一个源文件中,如果要根据所有函数的定义,直接抽出函数原型并导入到一个头文件中,可以通过如下命令实现:

技术分享

该命令的工作行为:首先对整个文件进行逐行搜索,搜索出每一个以"{"开头的行,将该行的上一行写入到collect_line.h文件中,从而达到将函数原型写入到头文件中的效果。这个例子是我自己想出来的,原书中没有该例子。


本章vi命令总结:

这章主要是对上一篇文章所学习的替换命令和正则表达式进行练习。正则表达式具有很强的技巧性,只有不断思考和不断尝试,才能扎实地掌握正则表达式,从而在文本编辑时找到更快速的方法。



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。