转载自:http://guoyoooping.blog.163.com/blog/static/135705183201003172232144/
#Author: ypguo<guoyoooping@163.com>
#Date: 2009.02.18
#Version: 1.0

[关键词] Vim s命令 g命令 文件格式 编码方式

[摘要] 本文总结了Vim的s命令和g命令, 以及文件换行格式和编辑格式的转换命令.

1. s命令

如果一个文本编辑器不支持正则表达式, 那么你所能做的可能就像Windows里的记事本, 拷
贝, 粘贴, 完事, 稍微复杂一点的操作就无能为力了. VI(M)做为各Unix发行版必备的文本
编辑工具, 对正则表达式的支持是非常强大的. 而体现正则表达式强大功能的除了Vim的查
找操作, 还有就是Vim的s命令了, 它可以将一个正则表达式替换成另一个正则表达式. 如
果你对正则表达式非常精通的话, 在Vim里执行替换, 查找操作可谓是如鱼得水. 我对正则
表达式也是从学Vim的时候学了一个皮毛, 把常用的一些命令记录下来, 以备将来忘记的时
候查找:

s命令的基本格式为:

    :s/str1/str2/ 用字串 str2 替换行中首次出现的字串 str1
    :s/str1/str2/g 用字串 str2 替换行中所有出现的字串 str1

由以上可知,g放在命令末尾,表示对搜索字串的每次出现进行替换;不加g,表示只对搜索字
串的首次出现进行替换,g放在命令开头,表示对正文中所有包含搜索字串的行进行替换 .

":%s/[Ctrl-v][Enter]//g" 去掉windows的行结束标志M, 命令分析: Ctrl-v 的作用是,
使得接着输入的回车键被认为是一个特殊字符, 而不是vim命令的结束.

":%s/\n\n\@!/ /"或":g/./,/^$/-1j"把以回车排版, 以空行分段的文本变成以回车分段的
文本, 如果不想保留段落间的空行":g/./,/^\s*$/j"

":%s/\s\+$//" 去掉所有的行尾空格:

":%s!\s*//.*!!" 去掉所有的"//"注释, 命令分析: 首先可以注意到, 这儿分隔符改用了
"!", 原因是在模式或字符串部分使用了"/"字符, 不换用其他分隔符的话就得在每次使用
"/"字符本身时写成"\/", 上面的命令得写成 " :%s/\s*\/\/.*//", 可读性较低. 命令本
身倒是相当简单, 用过正则表达式的人估计都知道"."匹配表示除换行符之外的任何字符吧
.

":%s!\s*/\*\_.\{-}\*/\s*! !g" 去掉所有的"/* */"注释, 命令分析:  (这个略有点复杂
了, 用到了几个不太常用的 Vim 正则表达式特性. "\_."匹配包含换行在内的所有字符;
"\{-}"表示前一个字符可出现零次或多次, 但在整个正则表达式可以匹配成功的前提下,
匹配的字符数越少越好; 标志"g"表示一行里可以匹配和替换多次. 替换的结果是个空格的
目的是保证像"int/* space not necessary around comments */main()"这样的表达式在
替换之后仍然是合法)

":%s/$/\r/g" 把以回车分段的文本变成以回车排版, 以空行分段的文本.

2. g命令

global命令是Vim最强大的命令之一(如果用好的话丝毫不逊于s命令), 将其摸透用熟可以
事半功倍, 影响g命令流行的最大问题是g命令大多很难理解, 而不深入理解, 要想记住几
十条命令是相当难的. 本节总结了我经常使用的几个g命令, 给出了解释, 以免将来忘记.

2.1 g命令的格式

可以用":help g"获得g命令的详细帮助. g命令的格式为:

[range]global/{pattern}/{command}

global命令在[range]指定的文本范围内(缺省为整个文件)查找{pattern},然后对匹配
到的行执行命令{command},如果希望对没匹配上的行执行命令,则使用global!或
vglobal命令。

2.2 g命令的例子

例1. 倒序文件行(即unix下的tac命令)

    :g/^/m 0

这条命令用行首标记/^/匹配文件的所有行(这是查找的一个常用技巧,如果用/./则是匹
配非空行,不满足本例要求),然后用move命令依次将每行移到第一行(第0行的下一行)
,从而实现了倒序功能。

例2.

    删除文件中所有的空行: :g/^\s*$/d(解释: ^\s*$是空行的正则表达式, 找出来后执行d, 即删除该行. )
    中把每段文字之后都加入一空行: :g/$/norm o (解释: 找到行尾, 执行o新开一行)
 
例3. 删除偶数行

    :g/^/+1 d

命令分析: 这条命令也是匹配所有行, 然后隔行删除(其中+1用以定位于当前行的下一行).
为什么是隔行呢?因为在对第一行执行+1 d命令时删除的是第二行, 而第二行虽然也被标
记了, 但已不存在了, 因此不会执行删除第三行的命令.

例4. 删除奇数行,

    :g/^/d|m.

分析分析:光是:g/^/d显然不行, 这会删除所有行, 我们需要用 move命令把偶数行的标记
去掉. 当然, 本例可以很简单的转换成4), 在此只是用来强调标记的概念.

例5. 把以回车分段的文本变成以回车排版, 以空行分段的文本.

    :ggVGgq

更多更复杂的例子请参考资料[1], 有很多命令直今还无法理解, 当然也不可能记住了.

3. 文件格式的转换

由于历史的原因, Windows用"\r\n"表示一行的结尾, Unix用"\r"表示, 而MacOS则用"\n",
Vim通常可以自动识别这些格式, 不用你操心. 但是你写的文档给别人看时, Windows的一
些应该程序可能不能识别Unix的换行符. 别人看到你的文件有可能是通往篇只有一行, 往
往会抱怨文件怎么不换行呢?

在Vim下修改文件的换行格式很简单, 在命令行执行下面的命令后保存即可

        :set fileformat=unix

这个文件就以Unix格式("\r")存盘了. 其它“怪招”:

    vi dos_file.txt
    :%s/^M//g

其中^M 必须是同时按 Ctrl+V+M ,表示回车。不是直接输入 ^M ,那没有用的, :-) 。

4. 文件编码方式的转换


Vim可以支持中文, 但是用过Vim的人大都有一段混沌经历, 一不小心文件就得乱码. 解决
乱码的问题相对简单, 只需要在.vimrc设好enc和fenc的值即可(参考学习笔记11, 晒晒我
的.vimrc). 设好enc和fenc的值可以保证vim正文里不出现乱码, 但是有一些插件(如
TxtBrowser)需要文档的enc和fenc一致, 才能正确显示中文的文档结构图, 这时就需要手
动地修改文件的fenc值. 其实很简单, 只有一句话, 例如你想将文件fenc值设为cp936, 在
命令行执行下面的命令, 保存退出即可.

    :set fenc=cp936

[参考资料]

[1]思凡的博客, VIM Global command,
http://blog.sina.com.cn/s/blog_4c45e4040100gkyc.html