范围 (Ranges) 其实很好理解,但很多 VIM 用户的理解不到位。
- 很多命令都可以加一个数字,用于指明操作范围
- 范围可以是一个行号,用于指定某一行
- 范围也可以是一对通过
,
或;
分割的行号 - 大部分命令,默认只作用于当前行
- 只有
:write
和:global
是默认作用于所有行的
范围的使用是十分直观的。以下为一些例子(其中,:d
为 :delete
的缩写):
命令 | 操作的行 |
---|---|
:d |
当前行 |
:.d |
当前行 |
:1d |
第一行 |
:$d |
最后一行 |
:1,$d |
所有行 |
:%d |
所有行(这是1,$ 的语法糖) |
:.,5d |
当前行至第 5 行 |
:,5d |
同样是当前行至第 5 行 |
:,+3d |
当前行及接下来的 3 行 |
:1,+3d |
第一行至当前行再加 3 行 |
:,-3d |
当前行及向上的 3 行(VIM 会弹出提示信息,因为这是一个保留的范围) |
:3,'xdelete |
第三行至标注 为 x 的那一行 |
:/^foo/,$delete |
当前行以下,以字符 "foo" 开头的那一行至结尾 |
:/^foo/+1,$delete |
当前行以下,以字符 "foo" 开头的那一行的下一行至结尾 |
需要注意的是,;
也可以用于表示范围。区别在于,a,b
的 b
是以当前行作为参考的。而 a;b
的 b
是以 a
行作为参考的。举个例子,现在你的光标在第 5 行。这时 :1,+1d
会删除第 1 行至第 6 行,而 :1;+1d
会删除第 1 行和第 2 行。
如果你想设置多个寻找条件,只需要在条件前加上 /
,比如:
:/foo//bar//quux/d
这就会删除当前行之后的某一行。定位方式是,先在当前行之后寻找第一个包含 "foo" 字符的那一行,然后在找到的这一行之后寻找第一个包含 "bar" 字符的那一行,然后再在找到的这一行之后寻找第一个包含 "quux" 的那一行。删除的就是最后找到的这一行。
有时,VIM 会在命令前自动添加范围。举个例子,如果你先通过 V
命令进入行选取模式,选中一些行后按下 :
进入命令模式,这时候你会发现 VIM 自动添加了 '
范围。这表示,接下来的命令会使用之前选取的行号作为范围。但如果后续命令不支持范围,VIM 就会报错。为了避免这样的情况发生,有些人会设置这样的按键映射::vnoremap foo :command
,组合键 Ctrl + u 可以清除当前命令行中的内容。
另一个例子是在普通模式中按下 !!
,命令行中会出现 :.!
。如果这时你如果输入一个外部命令,那么当前行的内容就会被这个外部命令的输出替换。你也可以通过命令 :?^$?+1,/^$/-1!ls
把当前段落的内容替换成外部命令 ls
的输出,原理是向前和向后各搜索一个空白行,删除这两个空白行之间的内容,并将外部命令 ls
的输出放到这两个空白行之间。
请参阅以下两个命令来获取更多帮助:
:h cmdline-ranges
:h 10.3