*usr_10.txt*	For Vim version 7.3 最近更新：2006年12月

		    Vim 用户手册 - by Bram Moolenaar
		译者：Nek_in http://vimcdoc.sf.net

			      做大修改


第四章我们已经介绍过作小修改的方法了。本章开始介绍如何重复多次修改和如何改动大
量的文字。这将包括使用可视模式处理一些文本块，还有使用一个外部程序去完成非常复
杂的功能。

|10.1|	记录与回放命令
|10.2|	替换
|10.3|	命令范围
|10.4|	global 命令
|10.5|	可视列块模式
|10.6|	读、写部分文件内容
|10.7|	排版文本
|10.8|	改变大小写
|10.9|	使用外部程序

     下一章：|usr_11.txt|  从崩溃中恢复
     前一章：|usr_09.txt|  使用 GUI 版本
       目录：|usr_toc.txt|

==============================================================================
*10.1*	记录与回放命令

"." 命令重复前一个修改操作。但如果你需要作一些更复杂的操作它就不行了。这时，记
录命令就变得很有效。这需要三个步骤：

1. "q{register}" 命令启动一次击键记录，结果保存到 {register} 指定的寄存器中。
   寄存器名可以用 a 到 z 中任一个字母表示。
2. 输入你的命令。
3. 键入 q (后面不用跟任何字符) 命令结束记录。

现在，你可以用 "@{register}" 命令执行这个宏。

现在看看你可以怎么用这些命令。假设你有如下文件名列表：

	stdio.h ~
	fcntl.h ~
	unistd.h ~
	stdlib.h ~

    而你想把它变成这样：

	#include "stdio.h" ~
	#include "fcntl.h" ~
	#include "unistd.h" ~
	#include "stdlib.h" ~

先移动到第一行，接着执行如下命令：

	qa			启动记录，并使用寄存器 a
	^			移到行首
	i#include "<Esc>	在行首输入 #include "
	$			移到行末
	a"<Esc>			在行末加上双引号 (")
	j			移到下一行
	q			结束记录

现在，你已经完成一次复杂的修改了。你可以通过重复三次 "@a" 完成余下的修改。

"@a" 命令可以通过计数前缀修饰，使操作重复指定的次数。在本例中，你可以输入：
>
	3@a


移 动 并 执 行

你可能有多个地方需要修改。只要把光标移动到相应的位置并输入 "@a" 命令即可。如果
你已经执行过一次，你可以用 "@@" 完成这个操作，这更容易输入一些。例如，你上次使
用 "@b" 命令引用了寄存器 b，下一个 "@@" 命令将使用寄存器 b。
    如果你对回放命令和 "." 命令作一个比较，你会发现几个区别。首先，"." 只能重
复一次改动。而在上例中，"@a" 可以重复多次改动，还能够执行移动操作。第二， "." 
只能记住最后一次变更操作。而寄存器执行命令允许你记录任何操作并使用象 "@a" 这样
的命令回放这些被记录的操作。最后，你可以使用 26 个寄存器，因此，你可以记录多达
26 个命令序列。


使 用 寄 存 器

用来记录操作的寄存器与你用来拷贝文本的寄存器是相同的。这允许你混合记录操作和其
它命令来操作这些寄存器。
    假设你在寄存器 n 中记录了一些命令。当你通过 "@n" 执行这些命令时，你发现这
些命令有些问题。这时你可以重新录一次，但这样你可能还会犯其它错误。其实，你可以
使用如下窍门：

	G			移到行尾
	o<Esc>			建立一个空行
	"np			拷贝 n 寄存器中的文本，你的命令将被拷到整个文
				件的结尾
	{edits}			象修改普通文本一样修改这些命令
	0			回到行首
	"ny$			把正确的命令拷贝回 n 寄存器
	dd			删除临时行

现在你可以通过 "@n" 命令执行正确的命令序列了。(如果你记录的命令包括换行符，请
调整上面例子中最后两行的操作来包括所有的行。)

追 加 寄 存 器

到此为止，我们一直使用小写的寄存器名。要附加命令到一个寄存器中，可以使用大写的
寄存器名。
    假设你在寄存器 c 中已经记录了一个修改一个单词的命令。它可以正常工作，但现
在你需要附加一个搜索命令以便找到下一个单词来修改。这可以通过如下命令来完成：
>
	qC/word<Enter>q

启动 "qC" 命令可以对 c 寄存器追加记录。由此可见，记录到一个大写寄存器表示附加
命令到对应的小写寄存器。

这种方法在宏记录，拷贝和删除命令中都有效。例如，你需要把选择一些行到一个寄存器
中，可以先这样拷贝第一行：
>
	"aY

然后移到下一个要拷贝的地方，执行：
>
	"AY

如此类推。这样在寄存器 a 中就会包括所有你要拷贝的所有行。

==============================================================================
*10.2*	替换						*find-replace*

":substitute" 命令使你可以在连续的行中执行字符串替换。下面是这个命令的一般形
式：
>
	:[range]substitute/from/to/[flags]

这个命令把 [range] 指定范围中的字符串 "from" 修改为字符串 "to"。例如，你可以把
连续几行中的 "Professor" 改为 "Teacher"，方法是：
>
	:%substitute/Professor/Teacher/
<
	备注:
	很少人会把整个 ":substitute" 命令完整敲下来。通常，使用命令的缩写形式
	":s" 就行了。下文我们将使用这个缩写形式。

命令前面的 "%" 表示命令作用于全部行。如果不指定行范围，":s" 命令只作用在当前行
上。|10.3| 将对 "行范围" 作深入的介绍。

默认情况下，":substitute" 命令只对某一行中的第一个匹配点起作用。例如，前面例子
中会把行：

	Professor Smith criticized Professor Johnson today. ~

修改成：

	Teacher Smith criticized Professor Johnson today. ~

要对行中所有匹配点起作用，你需要加一个 g (global，全局) 标记。下面命令：
>
	:%s/Professor/Teacher/g

对上面例子中的句子的作用效果如下：

	Teacher Smith criticized Teacher Johnson today. ~

":s" 命令还支持其它一些标志位，包括 "p" (print，打印)，用于在命令执行的时候打
印出最后一个被修改的行。还有 "c" (confirm，确认) 标记会在每次替换前向你询问是
否需要替换。执行如下命令：
>
	:%s/Professor/Teacher/c

Vim 找到第一个匹配点的时候会向你提示如下：
>
	replace with Teacher (y/n/a/q/l/^E/^Y)?

(中文翻译如下：
>
	替换为 Teacher 么 (y/n/a/q/l/^E/^Y)?
<
)

这种时候，你可以输入如下回答中的一个：

	y		Yes，是；执行替换
	n		No，否；跳过
	a		All，全部；对剩下的匹配点全部执行替换，不需要再确认
	q		Quit，退出；不再执行任何替换
	l		Last，最后；替换完当前匹配点后退出
	CTRL-E		向上滚动一行
	CTRL-Y		向下滚动一行


":s" 命令中的 "from" 部分实际上是一个 "匹配模式" (还记得吗？这是我们前面给
pattern 起的名字译者)，这与查找命令一样。例如， 要替换行首的 "the" 可以这样
写：
>
	:s/^the/these/

如果你要在 "from" 或者 "to" 中使用正斜杠，你需要在前面加上一个反斜杠。更简单的
方法是用加号代替正斜杠。例如：
>
	:s+one/two+one or two+

==============================================================================
*10.3*	命令范围

":substitute" 命令和很多其它的 ":" 命令一样，可以作用于选中的一些行。这称为一
个 "范围"。
    最简单的范围表达形式是 "{number},{number}"。例如：
>
	:1,5s/this/that/g

这会在 1 到 5 行上执行替换命令。(包括第 5 行)。"范围" 总是放在一个命令的前面。

如果只用一个数值，表示某个指定的行：
>
	:54s/President/Fool/

有些命令在不指定范围的时候作用于整个文件。要让它只作用于当前行可以用当前行范围
标识 "."。":write" 命令就是这样：不指定范围的时候，它写入整个文件，如果要仅写
入当前行，可以这样：
>
	:.write otherfile

文件的第一行行号总是 1，最后一行又是多少呢？"$" 字符用于解决这个问题。例如，要
修改当前行到文件末的全部内容，可以这样：
>
	:.,$s/yes/no/

我们前面使用的 "%" 就是 "1,$" 的缩写形式，表示从文件首到文件末。


在 范 围 中 使 用 模 式

假设你正在编辑一本书中的一章，并且想把所有的 "grey" 修改成 "gray"。但你只想修
改这一章，不想影响其它的章节。另外，你知道每章的开头的标志是行首的单词为
"Chapter"。下面的命令会对你有帮助：
>
	:?^Chapter?,/^Chapter/s=grey=gray=g

你可以看到这里使用了两个查找命令。第一个是 "?^Chapter?"，用于查找前一个行首的
"Chapter"，就是说 "?pattern?" 用于向前查找。同样，"/^Chapter/" 用于向后查找下
一章。
    为了避免斜杠使用的混淆，在这种情况下，"=" 字符用于代替斜杠。使用斜杠或使用
其它字符其实也是可以的。


加 减 号

上面的方案其实还是有问题的：如果下一章的标题行中包括 "grey"，这个 "grey" 也会
被替换掉。如果你正好想这样就最好，可是正好你不想呢？这个时候你需要指定一个偏
移。
    要查找一个模式，并且使用它的前一行，需要这样：
>
	/Chapter/-1

你可以用任意数值代替命令中的 1。要定位匹配点下的第二行，要这样：
>
	/Chapter/+2

偏移还可以用于其它范围指定符。看一下下面这个例子：
>
	:.+3,$-5

这指定当前行下面第三行到文件末倒数第五行的范围。


使 用 标 记

除了指定行号，(这需要记住并把它敲出来)，你还可以使用标记。
    在前面的例子中，你可以用标记指出第三章的位置。例如，用 "mt" 标记开头，再用
"mb" 标记结尾。然后你就可以用标记表示一个范围 (包括标记的那一行)：
>
	:'t,'b


可 视 模 式 和 范 围

你可以在可视模式中选中一些行。如果你现在输入 ":" 启动冒号命令模式，你会看到：
>
	:'<,'>

现在，你可以输入剩下的命令，这个命令的作用范围就是可视模式中指定的范围。

	备注:
	如果使用可视模式选中行的一部分，或者用 CTRL-V 选中一个文本列块，然后执
	行冒号命令，命令仍作用于整行，而不只是选中的范围。这可能会在以后的版本
	中修正。

'< 和 '> 实际上是标记，分别标识可视模式的开始和结尾。这个标记一直有效，直到选
中了其它的范围为止。你还可以用标记跳转命令 "'<" 跳转到选中文本的开始处。你还可
以把这个标记和其它标记混合，例如：
>
	:'>,$

这表示从选中部分的结尾到文件末。


指 定 行 数

如果你知道要修改多少行，你可以先输入一个数值再输入冒号。例如，如果你输入
"5:"，你会得到：
>
	:.,.+4

现在你可以继续你的命令，这个命令将作用于当前行及其后 4 行。

==============================================================================
*10.4*	global 命令

":global" 命令是 Vim 中一个更强大的命令 (之一)。它允许你找到一个匹配点并且在那
里执行一个命令。它的一般形式是：
>
	:[range]global/{pattern}/{command}

这有点象 ":substitute" 命令。只是它不替换文本，而是执行 {command} 指定的命令。

	备注:
	global 中执行的命令只能是冒号命令。普通模式命令不能在这里使用。如果需
	要，可以使用 |:normal| 命令。

假设你要把 "foobar" 修改为 "barfoo"，但只需要修改 C++ 风格的注释中的内容。这种
注释以 "//" 开头。所以可以使用如下命令：
>
	:g+//+s/foobar/barfoo/g

这个命令用 ":g" 开头，这是 ":global" 的缩写形式，就像 ":s" 是 ":substitute" 的
缩写形式一样。然后是一个匹配模式，由于模式中包括正斜杠，我们用加号作分隔符，后
面是一个把 "foobar" 替换成 "barfoo" 的替换命令。
    全局命令的默认范围是整个文件，所以这个例子中没有指定范围。这一点与
":substitute" 是不同的。后者只作用于一行。
    这个命令并非完美。因为 "//" 可能出现在一行的中间，但替换命令会把前后的匹配
点都替换了。

像 ":substitute" 一样，这里也可以使用各种各样的匹配模式。当你从后面的章节中学
会更多的关于模式的知识，它们都可以用在这里。

==============================================================================
*10.5*	可视列块模式

CTRL-V 命令可以选中一个矩形文本块。有几个命令是专门用来处理这个文本块的。

在可视列块模式中，"$" 命令有些特别。当最后一个移动命令是 "$" 时，整个可视列块
将被扩展到每一行的行尾。这种状态在你使用垂直移动命令的时候一直被保持，直到你使
用水平移动命令为止。就是说，用 "j" 命令会保持这种状态，而 "h" 会退出。


插 入 文 本

"I{string}<Esc>" 命令把 {string} 插到可视列块的每一行的左边。你用 CTRL-V 进入
可视列块模式，然后移动光标定义一个列块。接着输入 I 进入插入模式，并随后输入文
本。这时，你输入的内容只出现在第一行。
    然后你输入 <Esc> 结束输入，刚才输入的字符串将神奇地出现在每一行的可视区的
左边。例如：

	include one ~
	include two ~
	include three ~
	include four ~

把光标移到第一行 "one" 的 "o"上，输入 CTRL-V。然后用 "3j" 向下移动到 "four"。
现在你选中了四行的一个方块。接着输入：
>
	Imain.<Esc>

结果将是：

	include main.one ~
	include main.two ~
	include main.three ~
	include main.four ~

如果选中的块经过一个短行，并且这行没有任何内容包括在可视列块中，则新的文本不会
被插入到该行中。例如，对于下面的例子，用可视列块选中第一和第三行的 "long"，这
样第二行的文本将不会被包括在可视列块中：

	This is a long line ~
	short ~
	Any other long line ~

		  ^^^^ 用可视列块选中的部分

现在输入 "Ivery <esc>"。结果将是：

	This is a very long line ~
	short ~
	Any other very long line ~

可以注意到，第二行中没有插入任何文本。

如果插入的文本中包括一个新行，则 "I" 命令的效果与普通插入语句一样，只影响块的
第一行。

"A" 命令的效果与 "I" 命令一样，只是把文字插入可视列块的右边，而且在短行中会插
入文字。这样，你有在短行中插入文字与否的不同选择。
    "A" 在如下情况会有一些特别：选中一个可视列块然后用 "$" 命令使可视列块扩展
到行尾。然后用 "A" 命令插入文本，文件将被插入到 "每一行" 的行尾。
    还是用上面的例子，在选中可视列块后输入 "$A XXX<Esc>"，结果将是：

	This is a long line XXX ~
	short XXX ~
	Any other long line XXX ~

出现这个效果完全是 "$" 命令的作用，Vim 能记住这个命令，如果你用移动命令选中相
同的可视列块，是不会有这样的效果的。


修 改 文 本

可视列块中的 "c" 命令会删除整个可视列块并转入 "插入" 模式，使你可以开始文本，
这些文本会被插入可视列块经过的每一行。
    在上面的例子中，如果仍选中包括所有 "long" 的一个可视列块，然后输入
"c_LONG_<Esc>"，结果会变成：

	This is a _LONG_ line ~
	short ~
	Any other _LONG_ line ~

与 "I" 命令一样，短行不会发生变化。而且在插入的过程中，你不能断行。

"C" 命令从块的左边界开始删除所有行的后半段，然后状态切换到 "插入" 模式让你输
入文本。新的文本被插入到每一行的末尾。
    在上面的例子中，如果命令改为 "Cnew text<Esc>"，你将获得这样的结果：

	This is a new text ~
	short ~
	Any other new text ~

可以注意到，尽管只有 "long" 被选中，它后面的内容也被删除了。所以在这种情况下，
块的左边界才是有意义的。
    同样，没有包括在块中的行不会受影响。

还有一些命令只影响被选中的字符：

	~       交换大小写     (a -> A 而 A -> a)
	U       转换成大写     (a -> A 而 A -> A)
	u       转换成小写     (a -> a 而 A -> a)


以 一 个 字 符 填 充

要以某一个字符完全填充整个块，可以使用 "r" 命令。再次选中上例中的文本，然后键
入 "rx":

	This is a xxxx line ~
	short ~
	Any other xxxx line ~


	备注:
	如果你要在可视列块中包括行尾之后的字符，请参考 25 章的 'virtualedit' 
	特性。


平 移

">" 命令把选中的文档向右移动一个 "平移单位"，中间用空白填充。平移的起始点是可
视列块的左边界。
    还是用上面的例子，">" 命令会导致如下结果：

	This is a	  long line ~
	short ~
	Any other	  long line ~

平移的距离由 'shiftwidth' 选项定义。例如，要每次平移 4 个空格，可以用这个命
令：
>
	:set shiftwidth=4

"<" 命令向左移动一个 "平移单位"，但能移动的距离是有限的，因为它左边的不是空白
字符的字符会挡住它，这时它移到尽头就不再移动。


连 接 若 干 行

"J" 命令连接被选中的行。其实就是删除所有的换行符。其实不只是换行符，行前后的多
余空白字符会一起被删除而全部用一个空格取代。如果行尾刚好是句尾，就插入两个空格
(参见 'joinspaces' 选项)
    还是用那个我们已经非常熟悉的例子，这回的结果将是：

	This is a long line short Any other long line ~

"J" 命令其实不关心选中了哪些字符，只关心块涉及到哪些行。所以可视列块的效果与
"v" 和 "V" 的效果是完全一样的。

如果你不想改变那些空白字符，可以使用 "gJ" 命令。

==============================================================================
*10.6*	读、写文件的一部分

当你在写一封 e-mail，你可能想包括另一个文件。这可以通过 ":read {filename}" 命
令达到目的。这些文本将被插入到光标的下面。
    我们用下面的文本作试验：

	Hi John, ~
	Here is the diff that fixes the bug: ~
	Bye, Pierre. ~

把光标移到第二行然后输入：
>
	:read patch

名叫 "patch" 的文件将被插入，成为下面这个样子：

	Hi John, ~
	Here is the diff that fixes the bug: ~
	2c2 ~
	<	for (i = 0; i <= length; ++i) ~
	--- ~
	>	for (i = 0; i < length; ++i) ~
	Bye, Pierre. ~

":read" 支持范围前缀。文件将被插入到范围指定的最后一行的下面。所以
":$r patch" 会把 "patch" 文件插入到当前文件的最后。
    如果要插入到文件的最前面怎么办？你可以把文本插入到第 0 行，这一行实际上是
不存在的。在普通的命令的范围中如果你用这个行号会出错，但在 "read" 命令中就可
以：
>
	:0read patch

这个命令把 "patch" 文件插入到全文的最前面。


保 存 部 分 行

要把一部分行写入到文件，可以使用 ":write" 命令。在没有指定范围的时候它写入全
文，而指定范围的时候它只写入范围指定的行：
>
	:.,$write tempo

这个命令写入当前位置到文件末的全部行到文件 "tempo" 中。如果这个文件已经存在，
你会被提示错误。Vim 不会让你直接写入到一个已存在的文件。如果你知道你在干什么而
且确实想这样做，就加一个叹号：
>
	:.,$write! tempo

小 心："!" 必须紧跟着 ":write"，中间不能留有空格。否则这将变成一个过滤器命令，
这种命令我们在本章的后面会介绍。


添 加 内 容 到 文 件 中

本章开始的时候介绍了怎样把文本添加到寄存器中。你可以对文件作同样的操作。例如，
把当前行写入文件：
>
	:.write collection

然后移到下一个位置，输入：
>
	:.write >>collection

">>" 通知 Vim 把内容添加到文件 "collection" 的后面。你可以重复这个操作，直到获
得全部你需要收集的文本。

==============================================================================
*10.7*	排版文本

在你输入纯文本时，自动换行自然会是比较吸引的功能。要实现这个功能，可以设置
'textwidth' 选项：
>
	:set textwidth=72

你可能还记得在示例 vimrc 文件中，这个命令被用于所有的文本文件。所以如果你使用
的是那个配置文件，实际上你已经设置这个选项了。检查一下该选项的值：
>
	:set textwidth

现在每行达到 72 个字符就会自动换行。但如果你只是在行中间输入或者删除一些东西，
这个功能就无效了。Vim 不会自动排版这些文本。
    要让 Vim 排版当前的段落：
>
	gqap

这个命令用 "gq" 开始，作为操作符，然后跟着 "ap"，作为文本对象，该对象表示 "一
段" (a paragraph)。"一段" 与下一段的分割符是一个空行。

	备注:
	只包括空白字符的空白行不能分割 "一段"。这很不容易分辨。

除了用 "ap"，你还可以使用其它 "动作" 或者 "文本对象"。如果你的段落分割正确，你
可以用下面命令排版整个文档：
>
	gggqG

"gg" 跳转到第一行，"gq" 是排版操作符，而 "G" 是跳转到文尾的 "动作" 命令。

如果你没有清楚地区分段落。你可以只排版你手动选中的行。先移到你要格式化的行，执
行 "gqj"。这会排版当前行和下面一行。如果当前行太短，下面一行会补上来，否则多余
的部分会移到下面一行。现在你可以用 "." 命令重复这个操作，直到排版完所有的文
本。

==============================================================================
*10.8*	改变大小写

你手头有一个分节标题全部是小写的。你想把全部 "section" 改成大写的。这可以用
"gU" 操作符。先在第一列执行：
>
			     gUw
<	section header 	    ---->      SECTION header

"gu" 的作用正好相反：
>
			     guw
<	SECTION header	    ---->      section header

你还可以用 "g~" 来交换大小写。所有这些命令都是操作符，所以它们可以用于 "动作"
命令，文本对象和可视模式。
    要让一个操作符作用于当前行，可以执行这个操作符两次。例如，"d" 是删除操作
符，所以删除一行就是 "dd"。相似地，"gugu" 使整一行变成小写。这可以缩成 "guu"。
"gUgU" 可以缩成 "gUU" 而 "g~g~" 则是 "g~~"。例如：
>
				g~~ 
<	Some GIRLS have Fun    ---->   sOME girls HAVE fUN ~


==============================================================================
*10.9*	使用外部程序

Vim 有一套功能非常强大的命令，可以完成所有功能。但有些东西外部命令能够完成得更
好或者更快。
    命令 "!{motion}{program}" 用一个外部程序对一个文本块进行过滤。换句话说，它
用一个文本块作为输入，执行一个由 {program} 指定的外部命令，然后用该程序的输出
替代选中的文本块。
    如果你不熟悉 UNIX 的过滤程序，上面的描述可以说是比较糟糕的。我们这里举个例
子来说明一下。sort 命令能对一个文件排序。如果你执行下面的命令，未排序的文件
input.txt 会被排序并写入 output.txt。(这在 UNIX 和 Microsoft Windows 上都有效)
>
	sort <input.txt >output.txt

现在在 Vim 中完成相同的功能。假设你要对 1 到 5 行排序。你可以先把光标定位在第
一行，然后你执行下面的命令：
>
	!5G

"!" 告诉 Vim 你正在执行一个过滤操作。然后 Vim 编辑器等待一个 "动作" 命令来告诉
它要过滤哪部分文本。"5G" 命令告诉 Vim 移到第 5 行。于是，Vim 知道要处理的是第
1 行 (当前行) 到第 5 行间的内容。
    由于在执行一个过滤命令，光标被 Vim 移到了屏幕的底部，并显示一个 "!" 作提示
符。现在你可以输入过滤程序的名字，在本例中就是 "sort" 了。因此，你整个命令将
是：
>
	!5Gsort<Enter>

这个命令的结果是 sort 程序用前 5 行作为输入执行，程序的输出替换了原来的 5 行。

	line 55			      line 11
	line 33			      line 22
	line 11		-->	      line 33
	line 22			      line 44
	line 44			      line 55
	last line		      last line

"!!" 命令用于对当前行执行过滤命令。在 Unix 上，"date" 命令能打印当前的时间和日
期，所以，"!!date<Enter>" 用 "date" 的输出代替当前行。这在为文件加入时间戳的时
候非常有用。


如 果 命 令 不 执 行 怎 么 办

启动一个 shell，发送一个命令并捕获它的输出，这需要 Vim 知道这个 shell 程序是怎
么工作的。如果你要使用过滤程序，你最好需要检查一下下面的选项：

	'shell'		指定 Vim 用于执行外部命令的 shell。
	'shellcmdflag'	传给 shell 的参数
	'shellquote'	shell 程序使用的引号 (用于引用命令)
	'shellxquote'	用于命令和重定向文件名的引号
	'shelltype'	shell 程序的类型 (仅用于 Amiga)
	'shellslash'	在命令中使用正斜杠 (仅用于 MS-Windows 和相容系统)
	'shellredir'	用于把命令输出写入文件所使用的字符串

在 Unix 上，这几乎不是问题。因为总共只有两种 shell 程序："sh" 类的和 "csh" 类
的。Vim 会检查选项 'shell'，并根据它的类型自动设置这些参数。
   但在 MS-Windows 上，有很多不同的 shell 程序，所以你必须修改这些 shell 程序
以便过滤功能正常执行。详细情况请参考相应选项的帮助。


读 入 一 个 命 令 的 输 出

要把当前目录的内容读进文件，可以用如下命令：

Unix 上： >
	:read !ls
MS-Windows 上： >
	:read !dir

"ls" 或者 "dir" 的输出会被捕获并插入到光标下面。这好像读入一个文件一样，但是需
要加上一个 "!" 让 Vim 知道后面是一个命令。
    这些命令还可以带参数。而且前面还可以带一个范围用于告诉 Vim 把这行放在什么
地方：
>
	:0read !date -u

这将用 UTC 格式把当前的时间插入到文件开头。(当然了，你的 date 命令必须能够接受
-u 选项。) 注意 这与 "!!date" 的区别："!!date" 替代一行，而 ":read !date" 插入
一行。


把 文 本 输 出 到 一 个 命 令

Unix 命令 "wc" 用于统计单词数目。要统计当前文件有多少个单词，可以这样：
>
	:write !wc

这和前面的写入命令一样，但文件名前面改为一个 "!" 用于告诉 Vim 后面是一个要被执
行的外部命令。被写入的文本将作为指定命令的标准输入。这个输出将是：

       4      47     249 ~

"wc" 命令惜字如金。这表示你有 4 行，47 个单词和 249 个字符。

注意不要错写成：
>
	:write! wc

这会强制把当前文件存到当前目录的 "wc" 文件中。在这里空格的位置是非常重要的！


重 画 屏 幕

如果外部程序产生一个错误信息，屏幕显示就会乱掉。Vim 颇重效率，所以它只刷新那些
需要刷新的地方。可是它不可能知道其它程序修改了哪些地方。要强制 Vim 重画整个屏
幕：
>
	CTRL-L

==============================================================================

下一章：|usr_11.txt|  从崩溃中恢复

版权：参见 |manual-copyright|  vim:tw=78:ts=8:ft=help:norl:
