["x]<Del> 或 <Del> x dl
["x]x 删除 [count] 个光标所在及之后的字符 [到寄存器 x]
(非 linewise 行动作)。和 "dl" 相同。
<Del> 键不使用 [count] 计数。如果给出计数,其作用是删
除该计数的最后一位。
如果 <Del> 键行为与预期不符,参见 :fixdel 。要用于删
除换行符 (合并行),参见 'whichwrap'。
X dh
["x]X 删除 [count] 个光标之前的字符 [到寄存器 x] (非
linewise 行动作)。和 "dh" 相同。另见 'whichwrap'。
d
["x]d{motion} 删除 {motion} 动作覆盖的文本 [到寄存器 x]。例外见下。
dd
["x]dd 删除 [count] 行 [到寄存器 x], linewise 行动作。
D
["x]D 删除光标所在字符到当前行尾,并向后删除 [count]-1 行
[到寄存器 x] (非 linewise 行动作)。和 "d$" 同义。
'cpoptions' 里包含 '#' 标志位时 ( cpo-# ),忽略计数。
{Visual}["x]x 或 v_x v_d v_<Del>
{Visual}["x]d 或
{Visual}["x]<Del> 可视模式下,删除高亮文本 [到寄存器 x] (关于 {Visual},
参见 Visual-mode )。
{Visual}["x]CTRL-H 或 v_CTRL-H v_<BS>
{Visual}["x]<BS> 选择模式下,删除高亮文本 [到寄存器 x]。
{Visual}["x]X 或 v_X v_D v_b_D
{Visual}["x]D 可视模式下,删除高亮行 [到寄存器 x] (关于 {Visual},参
见 Visual-mode )。可视列块模式下,"D" 删除高亮文本,
以及直到行尾的所有内容。
:d :de :del :delete :dl :dp
:[range]d[elete] [x] 删除 [range] 范围内的所有行 (缺省: 当前行) [到寄存器
x]。
注意这些奇异的缩写形式:
:dl 删除并列出 ( :list )
:dell 同上
:delel 同上
:deletl 同上
:deletel 同上
:dp 删除并显示 ( :print )
:dep 同上
:delp 同上
:delep 同上
:deletp 同上
:deletep 同上
:[range]d[elete] [x] {count}
从 [range] 范围的结束行 (缺省: 当前行) 开始,删除
{count} 行 [到寄存器 x]。参见 cmdline-ranges 。
这些命令用于删除文本。除 :d 外,可用 . 命令重复执行,且所有删除操作均可撤
销。在可视模式下可以删除列块文本。有关寄存器的说明,参见 registers 。
d-special
d{motion} 命令的特例: 当动作不面向行、动作的起始和结束位置不在同一行、起始位置
之前只有空白、且结束位置之后没有非空白字符时,该删除会自动转为行动作。这可能会
删除原先想保留的空白行。要关闭此特殊行为,可用 o_v 操作符强制该动作面向字
符,或从 'cpoptions' 里删除 "z" 标志位 (见 cpo-z )。
'cpoptions' 包含 'E' 标志位时,如果试图删除空文本区域 (如在首列上按 "d0"),报
错。
J
J 合并 [count] 行,但至少包含两行。移除缩进,插入不超过
两个空格 (见下)。在缓冲区末行执行此操作会失败。[count]
如果过大,会自行缩减为剩余可用行数。
v_J
{Visual}J 可视模式下,合并高亮行,但至少包含两行。移除缩进,插入
不超过两个空格 (见下)。
gJ
gJ 合并 [count] 行,但至少包含两行。不插入也不删除任何空
格。
v_gJ
{Visual}gJ 可视模式下,合并高亮行,但至少包含两行。不插入也不删除
任何空格。
:j :join
:[range]j[oin][!] [flags]
合并 [range] 范围内的所有行。和 "J" 相同,但添加 [!]
时,合并操作不插入也不删除任何空格。缺省合并当前行与下
一行。
如果 [range] 的起始行和结束行相同,命令不执行任何操
作。
[flags] 可见 ex-flags 。
:[range]j[oin][!] {count} [flags]
合并 [range] 范围的结束行 (缺省: 当前行) 开始的
{count} 行。参见 cmdline-ranges 。和 "J" 相同,但添加
[!] 时,合并不插入也不删除任何空格。
[flags] 可见 ex-flags 。
这些命令会删除行间的 <EOL> (换行符),其实际效果是使多行合并成一行。除 :j
外,可用 . 命令重复执行,且所有操作均可撤销。
非 "gJ" 系列的命令会插入一个空格以替换 <EOL>,除非当前行末尾已有空白字符,或下
一行以 ')' 开头。非 "gJ" 系列的命令同时会删除下一行的所有起始空白。打开
'joinspaces' 选项时,这些命令在 '.'、'!' 或者 '?' 后插入两个空格而非一个 (但当
'cpoptions' 包括 'j' 标志位时,仅在 '.' 后插入两个空格)。
'formatoptions' 中的 'B' 和 'M' 标志位会修改多字节字符前后的空格插入行为,参见
fo-table 。
'[ 标记指向被合并行首行的原行尾位置, '] 标记指向合并后的最终行尾。
R
R 进入替换模式: 从光标所在位置开始,每输入一个字符就替换
一个已有字符。然后将输入文本重复 [count]-1 次。详见
Replace-mode 。
gR
gR 进入虚拟替换模式: 每输入一个字符就替换占据相同屏幕空间
的已有字符 (一个 <Tab> 从而可以可一次性替换多个字符)。
然后将输入文本重复 [count]-1 次。详见
Virtual-Replace-mode 。
c
["x]c{motion} 删除 {motion} 覆盖的文本 [到寄存器 x],然后进入插入模
式。'cpoptions' 包含 'E' 标志位时,如果无实际文本可删
除 (如执行 "cTx" 但光标位于 'x' 之后),会报错并拒绝进
行插入模式 (这与 Vi 兼容)。反之当 'cpoptions' 不包含
'E' 时,"c" 命令无论是否删除文本都会启动插入模式。
cc
["x]cc 删除 [count] 行 [到寄存器 x],然后进入插入模式。
linewise 行动作。置位 'autoindent' 时,会保留首行的
缩进。
C
["x]C 从光标位置删除到行尾,并向后删除 [count]-1 行 [到寄存
器 x],然后进入插入模式。和 c$ 等价 (非 linewise 行
动作)。
s
["x]s 删除 [count] 个字符 [到寄存器 x],然后进入插入模式。(s
代表替代 (Substitute))。和 "cl" 等价 (非 linewise 行
动作)。
S
["x]S 删除 [count] 行 [到寄存器 x],然后进入插入模式。和
"cc" 等价。 linewise 行动作。
{Visual}["x]c or v_c v_s
{Visual}["x]s 可视模式下,删除高亮文本 [到寄存器 x],然后进入插入模
式 (关于 {Visual},参见 Visual-mode )。
v_r
{Visual}r{char} 可视模式下,将所有高亮字符替换为 {char}。
CTRL-C 按本义插入。
v_C
{Visual}["x]C 可视模式下,删除高亮行 [到寄存器 x],然后进入插入模
式。可视列块模式下,行为有所不同,见 v_b_C 。
v_S
{Visual}["x]S 可视模式下,删除高亮行 [到寄存器 x],然后进入插入模式
(关于 {Visual},参见 Visual-mode )。
v_R
{Visual}["x]R 当前功能和 {Visual}["x]S 相同。后续版本可能会发生变
动。
备注:
- 可用 <Esc> 退出插入和替换模式。
- 要了解这些模式下的其他特殊字符,可见 "插入和替换模式" 一节 mode-ins-repl 。
- [count] 的效果只有在 Vim 退出插入或替换模式时才会生效。
- 当 'cpoptions' 选项包含 '$' 时,如果修改仅在一行内进行,Vim 会继续显示已删除
的文本,并在最后一个被删字符后显示 '$'。新插入的文本会覆盖被修改的文本。
有关寄存器的说明,参见 registers 。
替换模式和插入模式类似,区别在于每输入一个字符会同时删除一个原有字符。如果到达
行尾,Vim 会将后续输入的字符追加到行尾 (和插入模式相同)。在替换模式下,退格键
可恢复原有文本 (如有)。(参见 "插入和替换模式" 一节 mode-ins-repl )。
cw cW
特例: 光标在单词内部时,"cw" 和 "cW" 不会包含单词后的空白,而只修改到词尾。这
是因为 Vim 把 "cw" 解释为 修改-单词,而单词本身并不包括其后的空白。
{Vi 兼容: 如果光标在空白字符上且其后仍有空白字符,"cw" 只修改第一个空白;这属
于潜在漏洞,因为 "dw" 会删除所有空白;可通过 'cpoptions' 里的 'w' 标志位来恢复
Vi 兼容行为}
如果希望 "cw" 包含 单词后的空格,可用以下映射:
:map cw dwi
还有一个方案,可用 "caw" (另见 aw 和 cpo-z )。
:c :ch :change
:{range}c[hange][!] 用不同文本替换若干文本行。输入只包含一个 "." 的行来结
束替换文本的输入。{range} 省略时,该命令只置换当前行。
添加 [!] 后,会在本命令执行期间临时切换 'autoindent'。
此命令在 Vim9 脚本里不支持,因为极易和变量名产生混
淆。
r
r{char} 将光标所在字符替换为 {char}。{char} 是 <CR> 或 <NL>
时,则替换为换行符。要替换为真正的 <CR>,可输入 CTRL-V
<CR>。而输入 CTRL-V <NL> 会替换为空字符 <Nul>。
{char} 为 CTRL-E 或 CTRL-Y 时,会复制下一行或上一行的
对应字符 (和插入模式一致, i_CTRL-E 和 i_CTRL-Y )。
支持计数,例如 10r<C-E> 会从下一行复制 10 个字符。
给出 [count] 时,Vim 会用 {char} 连续替换 [count] 个字
符。不过,如果 {char} 为 <CR> 或 <NL>,Vim 只插入一个
换行符: 如 "5r<CR>" 会用一个换行符替换五个字符。
当 {char} 为 <CR> 或 <NL> 时,Vim 会自动缩进。效果等同
于先删除要替换的字符,再执行 "i<CR><Esc>"。
{char} 支持输入二合字母 digraph-arg 。
:lmap 映射会作用于 {char}。插入模式下的 CTRL-^ 命令
可切换此功能 i_CTRL-^ 。
'encoding' 为 Unicode 编码时,要使用组合字符,参见
utf-8-char-arg 。
gr
gr{char} 替换光标下的虚拟字符。替换操作基于屏幕显示位置,而非文
件实际存储位置。详见 gR 和 Virtual-Replace-mode 。
和 r 一样,支持使用计数。{char} 输入方式也与 r 类
似,但不能使用插入模式下有特殊含义的字符,包括大部分
CTRL-组合键。
digraph-arg
普通模式下,需要单字符参数的命令 (如 r 和 t ),在 'cpo' 不包含 'D' 标志位
时,可通过 digraphs 方式输入该字符: 先按 CTRL-K 再输入二合字母对应的两个字符。
{仅当编译时加入 +digraphs 特性才有效}
case
以下命令用于切换字母大小写。操作会使用当前生效的 locale 。参见 :language 。
这里会用到 LC_CTYPE 环境变量。
~
~ 打开 'notildeop' 时: 切换光标下字符的大小写,并将光标
右移。给出 [count] 时,对指定数量的字符执行此操作。
~{motion} 打 'tildeop' 时: 切换 {motion} 覆盖文本的大小写。
g~
g~{motion} 切换 {motion} 覆盖的文本的大小写。
g~g~ g~g~ g~~
g~~ 切换当前行的大小写。
v_~
{Visual}~ 可视模式下,切换高亮文本的大小写 (关于 {Visual},参见
Visual-mode )。
v_U
{Visual}U 可视模式下,使高亮文本转为大写 (关于 {Visual},参见
Visual-mode )。
gU uppercase
gU{motion} 使 {motion} 覆盖的文本转为大写。
例如:
:map! <C-F> <Esc>gUiw`]a
在插入模式下 按 CTRL-F,可使光标之前的单词转为大写。这
方便输入大写单词,只要先输入小写,再一键转换即可。
gUgU gUgU gUU
gUU 使当前行转为大写。
v_u
{Visual}u 可视模式下,使高亮文本转为小写 (关于 {Visual},参见
Visual-mode )。
gu lowercase
gu{motion} 使 {motion} 覆盖的文本转为小写。
gugu gugu guu
guu 使当前行转为小写。
g? rot13
g?{motion} 用 Rot13 对 {motion} 覆盖的文本进行编码。
v_g?
{Visual}g? 可视模式下,用 Rot13 对高亮文本进行编码 (关于
{Visual},参见 Visual-mode )。
g?g? g?g? g??
g?? 用 Rot13 对当前行进行编码。
要用标题大写 (title cap) 形式改写一行,即每个单词首字母大写,其余小写,可用:
:s/\v<(.)(\w*)/\u\1\L\2/g
递 增 与 递 减
CTRL-A
CTRL-A 将光标所在或后方的数值或字母增加 [count]。
v_CTRL-A
{Visual}CTRL-A 可视模式下,将高亮文本内的数值或字母增加 [count]。
v_g_CTRL-A
{Visual}g CTRL-A 可视模式下,将高亮文本内的数值或字母增加 [count]。如果
高亮跨越多行,每行将依次叠加额外的 [count] (即生成以
[count] 为步长的递增数列)。
例如,假定有如下数值列表:
1.
1.
1.
1.
将光标移动至第二个 "1.",可视选中后三行,按 g CTRL-A
会生成:
1.
2.
3.
4.
CTRL-X
CTRL-X 将光标所在或后方的数值或字母减去 [count]。
v_CTRL-X
{Visual}CTRL-X 可视模式下,将高亮文本内的数值或字母减去 [count]。
MS-Windows 上,此键被映射到剪切可视文本
dos-standard-mappings 。要屏蔽该映射,可用:
silent! vunmap <C-X>
v_g_CTRL-X
{Visual}g CTRL-X 可视模式下,将高亮文本内的数值或者字母减去 [count]。如
果高亮跨越多行,每行将依次多减一个 [count] (即生成以
[count] 为步长的递减数列)。
CTRL-A 和 CTRL-X 命令可用于:
- 带符号或无符号十进制数
- 无符号二进制、八进制和十六进制数
- 字母
具体应用的值取决于 'nrformats' 选项:
- 当 'nrformats' 包括 "bin" 时,Vim 将 '0b' 或 '0B' 开头的数值识别为二进制。
- 当 'nrformats' 包括 "octal" 时,Vim 将 '0' 开头的数值识别为八进制,除非数位
里包含 '8' 或 '9'。其他数值默认为十进制,并可带负号。
如果光标已经在数值上,命令会操作该数值;否则操作光标右侧数值。
- 当 'nrformats' 包括 "hex" 时,Vim 将 '0x' 或者 '0X' 开头的数值识别为十六进
制。数值最右侧的字母决定结果使用的大小写。如果当前数值不包含字母,Vim 会沿用
上次检测到的大小写。
- 当 'nrformats' 包括 "alpha" 时,Vim 会对光标所在或后方的字母进行增减。这可用
于构造字母编号的列表。
增减操作只会考虑十进制形式的前导负号。而不会考虑二进制、八进制和十六进制形式。
要一律忽略正负号,可用可视模式选中数值本身。再执行 CTRL-A 或 CTRL-X。
对于以零开头的数值 (包括八进制和十六进制),Vim 会尽可能保持字符总位数不变。
例如,在 "0077" 上执行 CTRL-A 会返回 "0100",在 "0x100" 上执行 CTRL-X 会返回
"0x0ff"。
特例: 'nrformats' 包含 "octal" 时,如果发现某数值以零开头但不是合法八进制 (因
为包含 '8' 或 '9'),会删除开头的零,以免结果被误认作八进制。
注意 'nrformats' 包含 "octal" 时,以零开头的十进制数会被错误识别,因为
会与八进制数混淆。
同样需要 注意,'nrformats' 同时包含 "bin" 和 "hex" 时,以 '0x' 或 '0X' 开头的
二进制数会被识别为十六进制,因为 '0b' 属于合法的十六进制字符。例如,在
"0x0b11" 上执行 CTRL-A 会返回 "0x0b12" 而非 "0x0b100"。
而当 'nrformats' 包含 "bin" 但不包含 "hex" 时,在 "0x0b11" 的 "0b11" 上执行
CTRL-A 会返回 "0x0b100"。
如果光标所在的数值超出了 32 或 64 位 (取决于 Vim 的编译方式) 可表示范围,会取
整到最接近的可表示数值,并忽略本次增减操作。例如,在 64 位环境下,在
18446744073709551616 上执行 CTRL-X 会返回 18446744073709551615。对更大的数值如
18446744073709551618 上的操作,结果相同。
CTRL-A 命令在宏命令里很有用。例如: 可按以下步骤可构造带数字编号的列表。
1. 建立首个列表项。确保以数值开头。
2. qa - 用寄存器 'a' 开始录制宏
3. Y - 抽出当前列表项
4. p - 将当前列表项的副本放置到下一行
5. CTRL-A - 递增计数
6. q - 停止录制宏
7. <count>@a - 重复抽出、放置和递增计数操作 <count> 次
将 文 本 左 移 或 右 移 shift-left-right
<
<{motion} 将 {motion} 覆盖的多行左移 'shiftwidth' 列。
打开 'vartabstop' 特性且 'shiftwidth' 选项设为零时,
缩进量以行首第一个非空白字符为准计算。
<<
<< 将 [count] 行左移 'shiftwidth' 列。
v_<
{Visual}[count]< 可视模式下,将高亮行左移 [count] 个 'shiftwidth' 列
(关于 {Visual},参见 Visual-mode )。
>
>{motion} 将 {motion} 覆盖的多行右移 'shiftwidth' 列。
打开 'vartabstop' 特性且 'shiftwidth' 选项设为零时,
缩进量以行首第一个非空白字符为准计算。
>>
>> 将 [count] 行右移 'shiftwidth' 列。
v_>
{Visual}[count]> 可视模式下,将高亮行右移 [count] 个 'shiftwidth' 列
(关于 {Visual},参见 Visual-mode )。
:<
:[range]< 将 [range] 指定的多行左移 'shiftwidth' 列。使用多个
'<' 可左移对应倍数的 'shiftwidth' 列。
:[range]< {count} 将 [range] 范围的结束行 (缺省为当前行) 开始的 {count}
行左移 'shiftwidth' 列。参见 cmdline-ranges 。使用多
个 '<' 可左移对应倍数的 'shiftwidth' 列。
:[range]le[ft] [indent] 将 [range] 指定的多行左对齐。缩进量设为 [indent] (缺省
为 0)。
:>
:[range]> [flags] 将 [range] 指定的多行右移 'shiftwidth' 列。使用多个
'>' 可右移对应倍数的 'shiftwidth' 列。
[flags] 部分可参见 ex-flags 。
:[range]> {count} [flags]
将 [range] 范围的结束行 (缺省为当前行) 开始的 {count}
行右移 'shiftwidth' 列。参见 cmdline-ranges 。使用多
个 '>' 可右移对应倍数的 'shiftwidth' 列。
[flags] 部分可参见 ex-flags 。
">" 和 "<" 命令可方便地调整代码缩进。缩进的白数量由 'shiftwidth' 选项控制。通
常 'shiftwidth' 为 8,但也可设为 3 等更小的值。
如果已经没有缩进可减少,左移命令会停止。而右移命令不会对空白行产生影响。
打开 'shiftround' 选项时,缩进量会被取整为 'shiftwidth' 的整数倍。
打开 'smartindent' 选项、或打开 'cindent' 且 'cinkeys' 包含带零值的 '#' 时,右
移操作不会对 '#' 开头的行产生影响 (这类通常是 C 语言预处理行,'#' 应保持在第一
列)。可通过 'cino' 选项改变此行为,参见 cino-# 。
'expandtab' 选项关闭 (缺省) 时,Vim 会尽量用 <Tab> 填充缩进。可用 ">><<" 将缩
进中的空格尽可能替换为 <Tab> 并保持缩进量不变 (必要时辅以少量空格)。而
'expandtab' 选项打开时,Vim 只使用空格缩进。此时 ">><<" 可将 <Tab> 替换成空格
(也可用 :retab! )。
要一次缩进多倍的 'shiftwidth' 列,可用可视模式或 : 命令。示例:
Vjj4> 将三行右移四个缩进位
:<<< 将当前行左移三个缩进位
:>> 5 将五行右移两个缩进位
:5>> 将第五行右移两个缩进位
4.1 过滤命令 filter
过滤程序是指接受文本作为标准输入,进行某些修改,再将结果输出到标准输出的程序。
可用下列命令将文本发送给过滤程序,并用其输出结果替换原文本。过滤程序的例子包括
"sort",用于对行按字母顺序排序;还有 "indent",用于格式化 C 程序文件 (需要能以
过滤程序方式工作的版本,并非所有的版本都支持)。'shell' 选项指定 Vim 用于执行过
滤程序的外壳程序 (另见 'shelltype' 选项)。可用 "." 重复上一次的过滤命令。Vim
不会识别 :! 命令后面以 '"' 开头的注释。
!
!{motion}{filter} 用外部程序 {filter} 过滤 {motion} 覆盖的多行。
!!
!!{filter} 用外部程序 {filter} 过滤 [count] 行。
v_!
{Visual}!{filter} 可视模式下,用外部程序 {filter} 过滤高亮行 (关于
{Visual},参见 Visual-mode )。
:{range}![!]{filter} [!][arg] :range!
要执行外部命令,参见 :! 。
用外部程序 {filter} 过滤 {range} 指定的多行文本。Vim
会将可选的感叹号替换成最后给出的命令,并追加可选参数
[arg]。Vim 把过滤命令的输出保存到临时文件,并将该文件
内容读入缓冲区 tempfile 。Vim 使用 'shellredir'
选项把过滤程序的结果重定向到临时文件。不过,如果关闭了
'shelltemp' 选项且环境支持 (如 Unix 系统),则使用管道
机制。
'cpoptions' 里包含 'R' 标志位时,除非使用了
:keepmarks 命令,否则会删除被过滤行里的位置标记。例
如:
:keepmarks '<,'>!sort
如果过滤后行数变少,被删除行里的位置标记无论如何都不会
保存。
=
={motion} 用 'equalprg' 选项指定的外部程序过滤 {motion} 覆盖的多
行。'equalprg' 选项为空 (缺省) 时,使用内置排版机制
C-indenting 和 'lisp'。不过,'indentexpr' 非空时,会
改用 indent-expression 缩进表达式机制。反之,如果
Vim 编译时没有包含内置排版机制,最终会使用外部的
"indent" 程序作为备用方案。
==
== 用 ={motion} 类似的方式过滤 [count] 行。
v_=
{Visual}= 可视模式下,用 ={motion} 类似的方式过滤高亮行。
tempfile setuid
Vim 使用临时文件来处理过滤、执行比较和用于 tempname() 函数。Unix 上,该文件会
放在一个私有目录里 (仅当前用户可访问),以防堵安全漏洞 (如符号链接攻击或文件被
其他用户读取等)。Vim 退出时,会自动删除该目录及其下所有文件 (仅对 Unix 有效,
其它系统需要自行清理)。如果 Vim 自身设置了 setuid 位,这种方式可能会出问题。因
为临时文件归 setuid 用户拥有,但过滤程序会使用原用户的权限运行。
Vim 会在以下目录中按顺序选择首个可用的目录来创建临时文件:
Unix: $TMPDIR、/tmp、当前目录、$HOME
Windows: $TMP、$TEMP、c:\TMP、c:\TEMP
MS-Windows 上,使用 GetTempFileName() 系统函数来生成临时文件。
其它系统上,则使用 tmpnam() 库函数。
4.2 替代 :substitute
:s :su
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
对 [range] 指定的每一行,将 {pattern} 的匹配项用
{string} 替代。
关于 {pattern},参见 pattern 。
{string} 可以是按本义出现的字符串,也可包含特殊字符。
参见 sub-replace-special 。
[range] 和 [count] 都省略时,仅对当前行进行替代。
[count] 给出时,对 [range] 范围的结束行开始的 [count]
行进行替代。[range] 省略时,从当前行开始。
E939 E1510
[count] 必须为正值 (最大值 2147483647)。
另见 cmdline-ranges 。
关于 [flags],参见 :s_flags 。
可用 / 之外的其他字符作为定界符,参见
pattern-delimiter 。
:[range]s[ubstitute] [flags] [count]
:[range]&[&][flags] [count] :&
重复执行最近一次 :substitute ,使用相同的匹配模式及替
代字符串,但不保留原有标志位。可在命令后追加 [flags]
(见 :s_flags )。
注意 :substitute 后不能使用 '&' 和 '#' 标志位。因为
它们会被识别为模式定界符。
:substitute 和 'c'、'g'、'i'、'I' 和 'r' 标志位之间
的空格并非必需,但在脚本里建议保留,以免歧义。
另见下述用于重复 :substitute 的两字母和三字母命令
:substitute-repeat 。
:[range]~[&][flags] [count] :~
重复执行最近一次 :substitute ,使用相同的替代字符串,
但使用最近使用的搜索模式作为匹配模式。相当于 :&r 。
关于 [flags],参见 :s_flags 。
&
& 相当于 :s (重复执行最近一次 :substitute )。注意 因
为不记住标志位,所以实际工作方式可能不尽相同。要保留原
有标志位,可用 :&& 。
g&
g& 相当于 :%s//~/& (在所有行上重复执行最近一次的
:substitute ,保留原有标志位,但使用前次匹配模式)。
例如,如果先执行替代命令 :s/pattern/repl/flags ,然后
执行 /search 搜索其他模式,此时 g& 会实际执行
:%s/search/repl/flags 。
助记: 全局 (global) 替代 (substitute)。
:snomagic :sno
:[range]sno[magic] ... 和 :substitute 类同,但总使用 'nomagic'。
:smagic :sm
:[range]sm[agic] ... 和 :substitute 类同,但总使用 'magic'。
:s_flags
在 :substitute 命令里,可用以下标志位:
:&&
[&] 必须是首个标志位: 保留最近一次替代命令原有的标志位。例如:
:&&
:s/this/that/&
注意 不带此标志位时, :s 和 :& 缺省不保留原有标志位。
[c] 确认每次替代。Vim 会高亮匹配的文本 (使用 hl-IncSearch )。确认时可输
入以下响应: :s_c
'y' 执行本次替代
'l' 执行本次替代后退出 (助记: "last",最后一次)
'n' 跳过本次匹配
<Esc> 退出替代
'a' 替代本次和其后所有匹配
'q' 退出替代
CTRL-E 上滚屏幕
CTRL-Y 下滚屏幕
打开 'edcompatible' 选项时,Vim 会记住 [c] 标志位并在下次使用时切换其
状态,在使用新的匹配模式时复位。
:s_e
[e] 如果模式匹配失败,不给出错误信息,尤其在映射中继续执行,如同没发生错误
一样。常用于避免因无匹配项 ("No match") 错误中断映射。不过,Vim 不会屏
蔽以下错误信息:
正则表达式不能用字母作分界
\ 后面应该跟有 /、? 或 &"
没有前一个替代正则表达式
多余的尾部字符
已中断
:s_g
[g] 替代当前行内所有匹配项。省略此标志位时,仅替代每行的首个匹配项。
打开 'edcompatible' 选项时,Vim 会记住 [g] 标志位并在下次使用时切换其
状态,在使用新的匹配模式时复位。打开 'gdefault' 选项时,缺省打开替代所
有匹配项的行为,而本标志位的作用是将其关闭。
:s_i
[i] 模式忽略大小写。不考虑 'ignorecase' 和 'smartcase' 选项。
:s_I
[I] 模式不忽略大小写。不考虑 'ignorecase' 和 'smartcase' 选项。
:s_n
[n] 仅报告匹配次数,并不实际执行替代。[c] 标志位会被忽略。匹配结果会按
'report' 为零的方式显示。可用于 count-items 。
使用 \= sub-replace-expression 时,表达式会在 sandbox 里对每个匹配
求值。
[p] 显示最后一次替代所在的行。 :s_p
[#] 和 [p] 类似,但在行首添加行号。 :s_#
[l] 和 [p] 类似,但以 :list 方式显示文本。 :s_l
:s_r
[r] 仅能与无参数的 :& 和 :s 配合使用。 :&r 和 :~ 功能等价: 当匹配模
式为空时,使用最近使用的搜索模式,而非上次替代命令或 :global 命令的
模式。当然,如果最近执行的搜索命令就是替代或 :global 命令,两者没有
实际区别。如果最近是 "/" 那样的搜索命令,则使用该命令的模式。
带参数的 :s 则已默认如此:
:s/blue/red/
/green
:s//red/ 或 :~ 或 :&r
最后这些命令会把 "green" 替代成 "red"。而
:s/blue/red/
/green
:&
最后这个命令会把 "blue" 替代成 "red"。
注意 没有用于改变模式 "魔术性" (magicness) 的标志位。为此,可改用其他命令,或
在模式中使用 /\v 之类项目。这是因为标志位只能在跳过模式之后才能被识别,而要
跳过模式,就必须先知道模式 "魔术性"。第二十二条军规!
替代命令所用的 {pattern} 为空时 (译者注: 如上所述,这只适用于无参数的替代命
令),会使用上次替代命令或 :global 命令的模式。如果没有这些,但存在上次搜索模
式,则使用该模式。而使用 [r] 标志位时,则会使用上次搜索模式,无论它来自替代、`:
global` 或普通搜索命令。
省略 {string} 时,视为用空串替代。即删除匹配内容。此时,{pattern} 之后的分隔
符也可省略。例如:
:%s/TESTING
会从所有行中删除首个 "TESTING"。
E1270
为兼容 Vi,老式脚本允许两种特例:
"\/{string}/" 和 "\?{string}?" 等同于 "//{string}/r" (使用上次搜索模式)。
"\&{string}&" 等同于 "//{string}/" (使用上次替代命令或 :global 模式)
(译者注:此处有误,两者并不相同,"//{string}/" 实际也使用上次搜索模式,见上)。
pattern-delimiter E146 E1241 E1242
包围模式和替代串的 '/' 也可改用其他单字节字符,这可用于搜索模式或替代串本身需
要使用 '/' 的场合。例如:
:s+/+//+
定界符可用大部分字符,但字母、数位、'\'、'"' 或 '|' 除外。在 Vim9 脚本里,也不
能用 '#',因为它可能被识别为注释开头。
模式的定义见 pattern 。在可视列块模式下,在模式中使用 /\%V 可使替代仅在列块
内生效,否则,替代会作用于整行。
sub-replace-special :s\=
{string} 以 "\=" 开头时,会被作为表达式求值,参见 sub-replace-expression 。
可用于实现复杂替换或用特殊字符替代。替代操作的递归深度限制为 4 层。 E1290
:s%
当 {string} 等于 "%",且 'cpoptions' 选项包含 '/' 时,会复用上次替代命令的替代
串 {string},见 cpo-/ 。
除此以外,{string} 字符串中包含的以下字符有特殊含义:
magic nomagic 动作
& \& 替代为完整的匹配文本 s/\&
\& & 替代为 & 字符
\0 替代为完整的匹配文本 \0 s/\0
\1 替代为第一个 () 里面的匹配文本 s/\1
\2 替代为第二个 () 里面的匹配文本 s/\2
.. .. s/\3
\9 替代为第九个 () 里面的匹配文本 s/\9
~ \~ 替代为上次替代命令的替代字符串 s~
\~ ~ 替代为 ~ 字符 s/\~
\u 使下一个字符转为大写 s/\u
\U 使其后字符转为大写,直到遇见 \E 为止 s/\U
\l 使下一个字符转为小写 s/\l
\L 使其后字符成为小写,直到遇见 \E 为止 s/\L
\e 结束 \u、\U、\l 和 \L 的作用 (注意: 不是 <Esc>!) s/\e
\E 同上 s/\E
<CR> 在当前位置将该行拆分成两行
(<CR> 需按 CTRL-V <Enter> 输入) s<CR>
\r 同上 s/\r
\<CR> 插入回车符 (CTRL-M)
(<CR> 需按 CTRL-V <Enter> 输入) s/\<CR>
\n 插入 <NL> (对应文件中的 <NUL> 字符)
(此处并非换行符) s/\n
\b 插入 <BS> s/\b
\t 插入 <Tab> s/\t
\\ 插入单个反斜杠 s/\\
\x x 代表上面未列出的任意字符: 保留用于未来扩展
这里的特殊含义也适用于 substitute() 函数的第三个参数 {sub},但有以下差异:
- % 总是插入百分号,与 'cpoptions' 无关。
- 总是假定有魔术性,与 'magic' 无关。
- ~ 总是插入波浪符。
- <CR> 和 \r 插入回车符 (CTRL-M)。
- \<CR> 没有特殊意义,只是 \x 之一。
示例:
:s/a\|b/xxx\0xxx/g 将 "a b" 修改为 "xxxaxxx xxxbxxx"
:s/\([abc]\)\([efg]\)/\2\1/g 将 "af fa bg" 修改为 "fa fa gb"
:s/abcde/abc^Mde/ 将 "abcde" 修改为 "abc"、"de" (两行)
:s/$/\^M/ 将 "abcde" 修改为 "abcde^M"
:s/\w\+/\u\0/g 将 "bla bla" 修改为 "Bla Bla"
:s/\w\+/\L\u\0/g 将 "BLA bla" 修改为 "Bla Bla"
注意: "\L\u" 可用于使单词整体转小写,仅首字母大写。此行为和 Vi 以及旧版 Vim 不
兼容,在旧版本中 "\u" 会抵消 "\L" 的效果。"\U\l" 同理。
注意: 在旧版中,CTRL-V 被特别处理。因为和 Vi 不兼容,该功能已被废弃,统一改用
反斜杠实现对应功能。
命令 文本 结果
:s/aa/a^Ma/ aa a<line-break>a
:s/aa/a\^Ma/ aa a^Ma
:s/aa/a\\^Ma/ aa a\<line-break>a
(要输入 ^M,需按 CTRL-V <CR>)
"\1","\2" 等序号对应模式里 "\(" 出现的先后顺序 (从左到右)。如果一个括号分组被
多次匹配,"\1","2" 等会取最后一次的匹配文本。例如:
:s/\(\(a[a-d] \)*\)/\2/ 将 "aa ab x" 修改为 "ab x"
"\2" 对应 "\(a[a-d] \)"。第一次匹配到 "aa ",第二次匹配到 "ab "。
括号分组和 '|' 组合使用时 (如 "\([ab]\)\|\([cd]\)"),两个模式必然有一个无法匹
配,所以 \1 或 \2 其中一个会为空。例如:
:s/\([ab]\)\|\([cd]\)/\1x/g 将 "a b c d" 修改为 "ax bx x x"
:sc :sce :scg :sci :scI :scl :scp :sg :sgc
:sge :sgi :sgI :sgl :sgn :sgp :sgr :sI :si
:sic :sIc :sie :sIe :sIg :sIl :sin :sIn :sIp
:sip :sIr :sir :sr :src :srg :sri :srI :srl
:srn :srp :substitute-repeat
2-字母和 3-字母的 :substitute 命令
这些命令用于重复执行最近一次的 :substitute 命令,并附加指定标志位。命令的首
字母总是 "s",后跟一到两个标志位字符。例如, :sce 相当于 :s///ce 。下表列出
所有合法组合,并非所有标志位组合都可用,因为有些组合是其他命令的缩写形式。
:substitute 命令速查表
| c e g i I n p l r
| c :sc :sce :scg :sci :scI :scn :scp :scl
| e
| g :sgc :sge :sg :sgi :sgI :sgn :sgp :sgl :sgr
| i :sic :sie :si :siI :sin :sip :sir
| I :sIc :sIe :sIg :sIi :sI :sIn :sIp :sIl :sIr
| n
| p
| l
| r :src :srg :sri :srI :srn :srp :srl :sr
例外情况:
:scr 代表 :scriptnames
:se 代表 :set
:sig 代表 :sign
:sil 代表 :silent
:sn 代表 :snext
:sp 代表 :split
:sl 代表 :sleep
:sre 代表 :srewind
基于表达式的替代 sub-replace-expression
sub-replace-\= s/\=
当替代字符串以 "\=" 开始时,其余部分会被解析为表达式。
除 "<CR>" 外, sub-replace-special 提到的字符特殊含义这里不再适用。<NL> 字符
会用于换行,在双引号字符串里也可用 "\n"。在 <NL> 之前加上反斜杠会插入真正的
<NL> 字符 (在文件里会以空字符 NUL 存储)。
"\=" 记法也可用于 substitute() 函数的第三个参数 {sub} 中,在那里,
sub-replace-special 提到的字符特殊含义完全不适用。具体来说,<CR> 和 <NL> 不
会被用于换行,而分别被解析为按本义的回车符和换行符。
表达式执行结果为 List 时,列表项会用换行符连接。结果是每个列表项会成为独立一
行,列表项本身也可包含换行。
要获取匹配文本,可用 submatch() 函数。完整的匹配文本可用 "submatch(0)"。首个
括号分组的匹配文本可用 "submatch(1)",以此类推。
小心: 表达式中不能出现替代分隔符!建议使用 "@" 或者 ":" 这类字符。而执行结果中
出现分隔符不会产生问题。
例如:
:s@\n@\="\r" .. expand("$HOME") .. "\r"@
会把换行符替代为包含 $HOME 环境变量值的新行。
s/E/\="\<Char-0x20ac>"/g
会把所有的 'E' 字符替代为欧元符号。详见 <Char-> 。
4.3 搜索并替代 search-replace
:pro :promptfind
:promptf[ind] [string]
弹出搜索对话框。 [string] 给出时,会被用作对话框的初始
搜索字符串。
{仅适用于 Win32、Motif 和 GTK GUI 环境}
:promptr :promptrepl
:promptr[epl] [string]
弹出搜索/替代对话框。 [string] 给出时,会被用作对话框
的初始搜索字符串。
{仅适用于 Win32、Motif 和 GTK GUI 环境}
4.4 调整制表 change-tabs
:ret :retab :retab!
:[range]ret[ab][!] [-indentonly] [{new-tabstop}]
将所有包含 <Tab> 的空白序列,替换为使用 {new-tabstop}
定义的新制表位组成的空白序列。{new-tabstop} 省略或为 0
时,Vim 会使用当前制表位 'tabstop'。
已有的制表符则总是按 'tabstop' 当前值计算宽度。
带 ! 时,Vim 同时会把只包含正常空格的字符串在合适时尽
可能换成制表符。
置位 'expandtab' 时,Vim 会把所有的制表替换成等价的空
格。
本命令会先把 'tabstop' 设为 {new-tabstop}。在缺省对整
个文件执行时,视觉上排版不应有任何变化。
给出 [-indentonly] 时,只替换行首的缩进空白。不改变其
他位置 (行中、行尾) 的连续空白。
警告: 本命令会修改 C 程序中的字符串常量内部的 <Tab> 字
符。要避免这个问题,请使用 "\t" 代替 (这本身也是良好的
编程习惯)。
:retab! 也会把空格序列换成 <Tab>,这可能会破坏
printf() 等函数里的格式字符串。
打开 +vartabs 特性时,可用逗号分隔的列数值列表代替单
个制表位值。列表中每个值对应一个制表位宽度。末值除外,
该值会应用到其后的所有制表位。
retab-example
下例使用自动命令和 ":retab" 来编辑文件,要求保存时使用制表位 8,但编辑时将制表
位改为 4。警告: 字符串常量内部的空格也会被修改!另见 'softtabstop' 选项。
:auto BufReadPost *.xx retab! 4
:auto BufWritePre *.xx retab! 8
:auto BufWritePost *.xx retab! 4
:auto BufNewFile *.xx set ts=4
quote
"{register} 指定下次的删除、抽出和放置命令 (译者注: 分别相当于剪贴
板的剪切、复制和粘贴操作) 使用寄存器 {register}。使用
大写字符寄存器时,删除和抽出操作会将内容追加到寄存器,
而非覆盖寄存器内容。特殊寄存器 "."、"%"、"#" 和 ":" 只
能用于放置命令。
:reg :registers
:reg[isters] 显示所有编号寄存器和命名寄存器的类型和内容。但不显示用
作 :redir 输出目标的寄存器 (译者注: 因为本命令的输出
本身也会被重定向)。
类型可以是以下几种:
"c" 用于面向字符 characterwise 文本
"l" 用于面向行 linewise 文本
"b" 用于面向列块 blockwise-visual 文本
:reg[isters] {arg} 显示 {arg} 里指定的编号寄存器和命名寄存器内容。例如:
:reg 1a
会显示寄存器 '1' 和 'a'。{arg} 内可使用空格分隔。
:di :dis :display
:di[splay] [arg] 同 :registers 。
y yank
["x]y{motion} 抽出 {motion} 覆盖的文本 [到寄存器 x]。'cpoptions' 里
包含 'E' 标志位时,如果没有任何内容可以抽出 (例如,在
第一列执行 "y0") 会报错。
yy
["x]yy 抽出 [count] 行 [到寄存器 x] linewise 行动作。
Y
["x]Y 抽出 [count] 行 [到寄存器 x] (同 yy , linewise 行动
作)。如果需要 "Y" 执行抽出从光标到行尾内容的操作 (这更
合乎逻辑,但与 Vi 不兼容),可用 `:map Y y$`。
zy
["x]zy{motion} 抽出 {motion} 覆盖的文本 [到寄存器 x]。仅在选择文本列
块时和 y 有区别,见 v_zy 。
v_y
{Visual}["x]y 可视模式下,抽出高亮文本 [到寄存器 x] (关于 {Visual},
参见 Visual-mode )。
v_Y
{Visual}["x]Y 可视模式下,抽出高亮行 [到寄存器 x] (关于 {Visual},参
见 Visual-mode )。
v_zy
{Visual}["x]zy 可视模式下,抽出高亮文本 [到寄存器 x]。选中列块时,不
会抽出列块每行末尾多余的空白。常与 zp 搭配使用 (关于
{Visual},参见 Visual-mode )。
:y :yank E850
:[range]y[ank] [x] 抽出 [range] 范围内的所有行 [到寄存器 x]。仅当启用
+clipboard 或 +clipboard_provider 特性时,才可以抽
出到 "* 或 "+ 剪贴板寄存器。
:[range]y[ank] [x] {count}
从 [range] 范围的结束行 (缺省: 当前行) 开始,抽出
{count} 行 [到寄存器 x]。参见 cmdline-ranges 。
p put E353 E1240
["x]p 在光标之后放置 [来自寄存器 x 的] 文本 [count] 次。
P
["x]P 在光标之前放置 [来自寄存器 x 的] 文本 [count] 次。
<MiddleMouse>
["x]<MiddleMouse> 在光标之前放置 [来自寄存器 x 的] 文本 [count] 次。省略
时默认使用 "* 寄存器。
光标会停留在新文本尾部。
仅当 'mouse' 包含 'n' 或者 'a' 时,鼠标操作才会生效。
使用滚轮鼠标时,如果经常不小心按中键粘贴了文本,可用以
下映射来关闭鼠标中键粘贴功能:
:map <MiddleMouse> <Nop>
:imap <MiddleMouse> <Nop>
如果还想关闭其多击版本。参见 double-click 。
gp
["x]gp 和 p 类似,但光标会停留在新文本之后的那个位置,而非
新文本尾部。
gP
["x]gP 和 P 类似,但光标会停留在新文本之后的那个位置。
:pu :put
:[line]pu[t] [x] 在第 [line] 行 (缺省: 当前行) 下方放置 [来自寄存器 x
的] 文本。总是 linewise 行动作,因而可用来将抽出的块
作为新行放置。
寄存器省略时,取决于 'clipboard' 选项: 'clipboard' 包
含 "unnamedplus" 时,会从 + 寄存器 quoteplus 粘贴,
否则当 'clipboard' 包含 "unnamed" 时,会从 * 寄存器
quotestar 粘贴,否则,从无名寄存器 quote_quote 粘
贴。
也可使用 '=' 寄存器,后跟可选表达式。表达式会继续到本
命令结束为止。如果希望 '|' 和 '"' 字符不终止本命令,需
要在其之前加上反斜杠转义。例如:
:put ='path' .. \",/test\"
'=' 之后如果未提供表达式,Vim 会使用上次使用的表达式。
可用 `:dis =` 察看。
:[line]pu[t]! [x] 在第 [line] 行 (缺省: 当前行) 上方放置 [来自寄存器 x
的] 文本。
:ip :iput
:[line]ip[ut] [x] 和 :put 类似,但放置后自动调整缩进,和当前行对齐。
:[line]ip[ut]! [x] 和 :put! 类似,但放置后自动调整缩进,和当前行对齐。
["x]]p 或 ]p ]<MiddleMouse>
["x]]<MiddleMouse> 和 p 类似,但放置后自动调整缩进,和当前行对齐。
仅当 'mouse' 包含 'n' 或 'a' 时,鼠标操作才会生效。
["x][P 或 [P
["x]]P 或 ]P
["x][p 或 [p [<MiddleMouse>
["x][<MiddleMouse> 和 P 类似,但放置后自动调整缩进,和当前行对齐。
仅当 'mouse' 包含 'n' 或 'a' 时,鼠标操作才会生效。
["x]zp 或 zp zP
["x]zP 和 p 和 P 类似,但粘贴列块时不会补全尾部空白。因此
插入的文本不会总是矩形对齐。常与 v_zy 搭配使用。
可以使用这些命令从一处到另一处复制文本。首先用抽出、删除或者修改命令将文本存入
寄存器,然后用放置命令写入寄存器内容。也可用这些命令将文本从一个文件移动到另一
个文件,因为 Vim 在切换缓冲区时会保留所有寄存器内容 (可用 CTRL-^ 命令在文件间
快速切换)。
linewise-register characterwise-register
可用 . 重复执行放置命令 ( :put 命令除外),同时支持撤销。如果存入寄存器文本
的命令是 linewise 行动作,Vim 会在当前行下方 ("p") 或上方 ("P") 放置文本。否
则,Vim 会在光标之后 ("p") 或之前 ("P") 放置。 :put 命令总在下一行放置文本,
而 :put! 则使用上一行。
常用技巧: 命令序列 "xp" 可用于交换两个字符。而 "ddp" 可用于交换两行。"deep" 则
可用于交换两个单词 (光标应先放在首个单词之前的空白上)。
放置命令完成后, '] 或 `] 命令可跳转到放置内容的末尾,而 '[ 或 `[ 可跳
转到放置内容的开头。
put-Visual-mode v_p v_P
在可视模式下,使用 p 或 P 之类的放置命令时,Vim 会试图用寄存器内容覆盖选中
文本。最终效果取决于选择区域类型以及寄存器文本类型。对于列块选择,同时取决于列
块的大小、以及边界位置是否位于已有字符上 (实现细节: 实际操作是先在选择区之后放
置寄存器内容,然后再删除选中文本)。
使用 p 时,原先的选中文本会被放入无名寄存器 (可能也同步到选择区和/或剪贴
板)。便于后续将该文本放置到他处。此操作无法重复。
使用 P 时,不会改动无名寄存器 (同样也不会改动选择区或剪贴板),此操作可以重复
执行,但被删除的文本无法再被使用。如需要多次重复替换,可用 p 配合其他寄存
器。例如,先抽出要复制的文本到寄存器 "0,可视化选择要替换的文本,然后使用
"0p 。可重复任意多次,每次都会更新无名寄存器。
blockwise-put
当 (面向字符) 寄存器包含的是单行文本时,如果选中可视列块并进行放置,该文本会重
复替换所选的每一行,从而用寄存器内容的多份副本替换列块区域。示例:
- 先用 yw 抽出单词 "TEXT" 到某寄存器
- 可视选择列块,如下面文本里 "v" 标识的区域 (选中头尾,按 CTRL-V ):
aaavvaaa
bbbvvbbb
cccvvccc
- 按 p ,结果是:
aaaTEXTaaa
bbbTEXTbbb
cccTEXTccc
blockwise-register
使用列块可视模式命令文本存入寄存器后,放置命令会将文本列块插入在当前行及后续
行中,光标列之前 ( P ) 或之后 ( p )。Vim 会确保整个文本列块从同一列开始。因此
插入后的效果与最初抽出或删除时保持一致。为此,Vim 可能会将部分 <Tab> 字符替换
为空格以对齐文本。不过,如果列块宽度不是 <Tab> 宽度的整数倍,并且插入位置之后
的文本包含 <Tab>,那些文本可能会出现对齐问题。
可用 zP / zp 来粘贴面向列块寄存器,这样不会在末尾附加多余的空白。
注意 在执行面向字符的抽出命令后,Vim 会将光标定位在距离缓冲区开头最近的 (首个)
抽出字符上。这意味着 yl 不会移动光标,而 yh 会将光标向左移动一个字符。
逻辑: 在 Vi 里, y 命令后跟一个反向移动作时,因为跳过屏幕重绘,光标
有时不会移动到抽出内容的首个字符。Vim 遵循 POSIX 规范,因此总
会移动光标到首个字符处。
在执行面向行的抽出命令后,光标会定位在首行,但列位置保持不变,所以光标未必会移
动到抽出内容的首个字符。
共有十种类型的寄存器: registers {register} E354
1. 无名寄存器 ""
2. 10 个编号寄存器 "0 到 "9 (译者注: 最近抽出、最近及更早跨行删除)
3. 行内删除寄存器 "-
4. 26 个命名寄存器 "a 到 "z 或 "A 到 "Z
5. 三个只读寄存器 ":、". 和 "% (译者注: 最近命令行、最近插入文本、当前文件名)
6. 轮换缓冲区寄存器 "#
7. 表达式寄存器 "=
8. 选择和拖放寄存器 "*、"+ 和 "~ (译者注: 主选择、剪切、拖放)
9. 黑洞寄存器 "_
10. 最近搜索模式寄存器 "/
1. 无名寄存器 "" quote_quote quotequote
Vim 通过 "d"、"c"、"s"、"x" 等命令删除的内容、以及 "y" 等命令抽出的文本,都会
自动存入本寄存器,即使同时指定了其他寄存器 (如 "xdd ) 也不例外。其效果相当于
无名寄存器始终指向最近一次使用的寄存器。使用大写寄存器追加内容时,无名寄存器和
命名寄存器会保存相同的文本。'_' 寄存器是唯一例外。 "_dd 不会将删除文本存入任
何寄存器。
不指定寄存器的放置命令 ( p 或 P ) 默认使用无名寄存器。也可显式使用 '"' 作为
名字来访问本寄存器,也就是连续输入两个双引号。写入 "" 寄存器的实际效果相当于写
入寄存器 "0。
{Vi: 切换文件时,寄存器内容会丢失,且没有 '"' 别名}
2. 编号寄存器 "0 到 "9 quote_number quote0 quote1
quote2 quote3 quote4 quote9
Vim 将抽出和删除命令的文本存入这些编号寄存器。
编号寄存器 0 存放最近抽出的文本,除非该命令用 ["x] 显式指定了其他寄存器。
编号寄存器 1 存放最近删除或修改的文本 (即使该命令指定了其他寄存器也一样)。
但删除文本少于一行时,会改用行内删除寄存器 ( quote- );以下移动命令配合删除操
作操作时是例外: % 、 ( 、 ) 、 ` 、 / 、 ? 、 n 、 N 、 { 和 } ,这些命令在
文本少于一行时,使用 "- 寄存器,但同是总是使用寄存器 1 (为了与 Vi 兼容)。注意
这些字符可能被映射 (如 matchit 插件会映射 % 字符)。
每当执行新的删除和修改时,Vim 会把上一次的寄存器 1 的内容复制到寄存器 2,2
到 3,依此类推。而寄存器 9 的原有内容会被丢弃。
{Vi: 寄存器 0 不存在}
3. 行内删除寄存器 "- quote_- quote-
本寄存器保存少于一行内容的删除文本,除非该命令用 ["x] 显式指定了其他寄存器。
4. 命名寄存器 "a 到 "z 或者 "A 到 "Z quote_alpha quotea
Vim 仅在手动指定时,才使用命名寄存器。使用小写字母时,会覆盖原有内容,而使用大
写字母时,会向原有内容追加文本。'cpoptions' 里包含 '>' 标志位时,追加文本前会
自动插入一个换行符。
5. 只读寄存器 ":、". 和 "%
特殊寄存器 '%'、':' 和 '.' 只读。仅可在 p 、 P 、 :put 命令以及 CTRL-R (插入
和命令行模式下) 中使用。
quote_. quote. E29
". 存放最近一次插入的文本 (和插入模式命令 CTRL-A 和 CTRL-@ 插入的
内容一致)。注意: 本寄存器不适用于命令行上的 CTRL-R。后者的工作
方式稍有不同,例如,文本是按本义插入而不是通过放置命令
('textwidth' 和其它选项会影响插入文本里的特殊字符,因此未必适
合在命令行上插入)。
quote_% quote%
"% 存放当前文件名。
quote_: quote: E30
": 存放最近执行过的命令行。例如: 用 "@:" 可重复执行上一条命令行命
令。
仅当手动输入至少一个字符的命令才会存入此寄存器。完全由映射触发
执行的命令,不会覆盖本寄存器内容。
{仅当编译时加入 +cmdline_hist 特性才有效}
quote_# quote#
6. 轮换文件寄存器 "#
本寄存器存放当前窗口的轮换文件名。会直接影响 CTRL-^ 命令的行为。
本寄存器可写,主要用于插件修改后手动还原其原值。写入时也接受缓冲区号:
let altbuf = bufnr(@#)
...
let @# = altbuf
如果指定的缓冲区号不存在,会报错 E86 。
也可接受已有缓冲区名,已进行匹配:
let @# = 'buffer_name'
如果有多个缓冲区匹配该名,报错 E93 ,如果没有任何缓冲区匹配该名,报错 E94 。
7. 表达式寄存器 "= quote_= quote= @=
这并不是真正用来存放文本的寄存器。而是用来在需要使用寄存器的命令中直接执行表达
式的特殊通道。表达式寄存器可读写。
" 或 CTRL-R 之后输入 '=' 时,光标会跳转到命令行,此时可输入任意表达式 (见
expression )。支持所有标准命令行编辑功能,并拥有专属的表达式历史记录。按回车
结束命令行时,Vim 会计算表达式结果。如果用 <Esc> 结束,Vim 中止表达式的计算。
如果不输入任何内容直接按回车,Vim 会使用上一次输入的表达式 (类似于 "/" 命令)。
表达式的计算结果必须能转换为字符串。数值结果会被自动转为字符串。对 p 和
:put 命令,浮点数结果也会被自动转为字符串。列表结果中,每个列表项会转成字符
串并被单独作为一行。字典结果也被转为字符串。函数引用结果会报错 (必须手动用
string() 转换)。
"= 寄存器用于 p 命令时,计算结果字符串会在 <NL> 字符处断开。如果该字符串以
<NL> 结尾,则被视为面向行寄存器。
8. 选择和拖放寄存器 "*、"+ 和 "~
这几个寄存器用于 GUI 界面中存放选中的文本。参见 quotestar 和 quoteplus 。
如果剪贴板不可用或工作异常,会自动改用无名寄存器。在 Unix 上,仅当编译时加入
+xterm_clipboard 特性才能使用剪贴板。
注意 "* 和 "+ 仅在 X11 系统上有差别。二者差异可见 x11-selection 。
在 MS-Windows 上,"* 和 "+ 的完全等效,参见 gui-clipboard 。
quote_~ quote~ <Drop>
只读寄存器 "~ 会存放最近一次拖放操作操作的文本。当有内容拖放到 Vim 内时,"~ 寄
存器会自动被填充,同时触发 <Drop> 虚拟键以作通知。用户可自定义映射该按键;缺省
行为 (全模式通用) 是在光标位置插入 "~ 寄存器的内容。
{仅当编译时加入 +dnd 特性才有效,目前只适用于 GTK GUI 版本}
注意: 仅当拖放普通文本到 Vim 时,才使用 "~ 寄存器。URI 链接列表的拖放会由程序
内部处理。
9. 黑洞寄存器 "_ quote_
写入该特殊寄存器不会产生任何效果。可用于删除文本,而不影响任何常规寄存器。读取
本寄存器时,不返回任何内容。
10. 最近搜索模式寄存器 "/ quote_/ quote/
本寄存器存放最近一次的搜索模式。供 n 命令和 'hlsearch' 使用。可用 :let 写
入修改。无需实际执行搜索,就能让 'hlsearch' 高亮匹配不同的内容。本寄存器无法通
过抽出或删除操作存入。搜索方向则可通过 v:searchforward 获取。
注意 从函数返回时,本寄存器值被自动复原 function-search-undo 。
@/
可用 :let 命令为寄存器赋值 :let-@ 。例如:
:let @/ = "the"
使用放置命令而不显式指定寄存器时,Vim 会使用上次被填充内容的寄存器 (相当于无名
寄存器的内容)。如需确认将被放置的内容,可用 :dis 命令查看 (该命令会显示所有
的命名和编号寄存器;无名寄存器标记为 '"')。
以下三个命令总是用于整行。
:[range]co[py] {address} :co :copy
将 [range] 范围内的所有行复制到 {address} 指定行的下
方。
:t
:t 同 :copy 。
Vim9 脚本里不支持本命令,因为容易和变量名混淆。
:[range]m[ove] {address} :m :mo :move E134
将 [range] 范围内的所有行移动到 {address} 指定行的下
方。
执行移动时,会自动清除 [range] 范围内所有的文本属性。
见 text-prop-cleared 。
:[range]ce[nter] [width] :ce :center
在 [range] 范围内的行和 [width] 限定的列宽内将文本居中
对齐。
[width] 缺省使用 'textwidth',为 0 时默认采用 80 列。
:[range]ri[ght] [width] :ri :right
在 [range] 范围内的行和 [width] 限定的列宽内将文本靠右
对齐。
[width] 缺省使用 'textwidth',为 0 时默认采用 80 列。
:le :left
:[range]le[ft] [indent]
左对齐 [range] 范围内的所有行。缩进量设为 [indent] (缺
省为 0)。
gq
gq{motion} 对 {motion} 动作覆盖的所有行进行排版。
排版会按以下优先级顺序选择方式:
1. 'formatexpr' 非空时,计算该表达式进行排版。每个缓冲
区可有不同的选项值。
2. 'formatprg' 非空时,调用指定的外部程序进行排版。
3. 否则,使用内置排版机制。
第三种方式 (内置排版机制) 规则如下。
'textwidth' 选项控制排版行的行宽 (见下)。该选项为 0
时,默认自动使用屏幕宽度 (但最大不超过 79 列)。
'formatoptions' 选项控制排版的方式,见 fo-table 。
排版结束后,光标会停在末行的首个非空白字符处。
注意:旧版里,"Q" 是排版命令。现在已改为启动 Ex 模式。
如果想恢复排版功能,可用以下映射:
:nnoremap Q gq
gqgq gqgq gqq
gqq 排版当前行。带 [count] 时,排版当前行开始的相应数量的
行。
v_gq
{Visual}gq 可视模式下,排版高亮文本 (关于 ({Visual},参见
Visual-mode )。
gw
gw{motion} 对 {motion} 动作覆盖的行进行排版。和 gq 类似,但排版
后光标恢复原位。而且也不考虑 'formatprg' 和
'formatexpr' 选项 (即,只使用内置排版机制)。
gwgw gwgw gww
gww 使用 gw 方式排版当前行。
v_gw
{Visual}gw 可视模式下,使用 gw 方式排版高亮文本 (关于
{Visual},参见 Visual-mode )。
例如: 要排版当前段落,可用: gqap
gqap
gq 命令执行完毕后,光标会跟随移动命令移动。这样便于 "." 重复执行连续排版。例
如, gqj (对当前行和下一行进行排版) 和 gq} (对当前行到段落尾进行排版) 都能
和此方式良好配合。注意: 设置 'formatprg' 时, gq 会把光标留在排版后的首行 (这
和过滤命令的行为一致)。
要在排版当前段落后光标恢复原位,可用:
gwap
要使段落自动排版,可在 'formatoptions' 里包含 'a' 标志位。参见 auto-format 。
'autoindent' 选项打开时,Vim 会沿用首行的缩进量,统一排版后续所有行。
排版不会影响空行 (但会影响仅有空白字符的行!)。
合并行的操作应用 'joinspaces' 选项。
可将 'formatexpr' 选项设置为表达式来实现自定义排版,也可以将 'formatprg' 选项
设置为外部排版程序。'textwidth' 和其他 Vim 选项对外部排版程序不起作用。
format-formatexpr
可将 'formatexpr' 选项设为 Vim 脚本函数,实现缓冲区的自定义排版。此功能常用于
ftplugin ,因为排版方式高度依赖于文件类型。为此,建议使用 autoload 脚本,仅
在需要时才载入对应脚本,节省性能。该脚本应命名为 <filetype>format.vim。
例如,随 Vim 官方发布提供的 $VIMRUNTIME/ftplugin 目录里的 XML 文件类型插件会将
'formatexpr' 选项设为:
setlocal formatexpr=xmlformat#Format()
对应的自定义函数 xmlformat#Format() 在以下文件中定义:
$VIMRUNTIME/autoload/xmlformat.vim
下方示范脚本可用于删除选中文本行尾空白。将其存放在用户 autoload 目录 (如
~/.vim/autoload/format.vim):
func! format#Format()
" 仅在手动执行 gq 命令时生效
if mode() != 'n'
" 其他情况下使用 Vim 内置排版机制
return 1
endif
let lines = getline(v:lnum, v:lnum + v:count - 1)
call map(lines, {key, val -> substitute(val, '\s\+$', '', 'g')})
call setline('.', lines)
" 不使用内置排版机制!
return 0
endfunc
然后,打开该自定义排版方式:
setlocal formatexpr=format#Format()
注意: 插入模式下 (一般这意味着插入文本导致文本长度超出 'textwidth' 限制) ,此
函数会直接返回非零值。此时,Vim 会使用缺省的内置排版机制。
反之,使用 gq 命令排版文本时,函数会读取选中行,清除拖尾空白并在原地放存。需
要把单行拆分为多行时,小心不要覆盖任何原有内容。
在插入或替换模式下,自动排版文本时需格外留意,防止函数递归调用。可用 'debug'
选项辅助调试。
right-justify
Vim 没有内置命令,实现文本的靠右控制对齐 (right justify)。可用 "par" 等外部命
令实现 (如 :.,}!par 可对当前位置到段落尾为止的文本进行排版),也可直接设置
'formatprg' 为 "par"。
format-comments
用户手册的 30.6 一节给出注释排版的总览。
Vim 可以自动对注释的插入和排版进行特殊处理。通过行首 (会忽略空白字符) 的特定字
符串 (即注释前缀),Vim 可识别注释。可以使用三种不同类型的注释:
- 每行的开头都出现注释字符串。例如外壳脚本中以 "#" 开头的注释类型。
- 注释字符串仅出现在首行,后续行不出现。例如本列表使用的短横线 "-" 可被看作一
例。
- 三段式注释,包括起始字符串,结束字符串,和中间可选行的起始字符串。起始、中
间、结束字符串各不相同。例如 C 语言风格的注释:
/*
* this is a C comment
*/
'comments' 选项是一个以逗号分隔的部分列表。每个部分定义一种类型的注释字符串
(注释前缀)。一个部分的格式是:
{flags}:{string}
{string} 是必须出现的字符串 (不作转义)。
{flags} 可包含以下标志位的组合:
n 嵌套注释: 允许混合不同的嵌套部分。例如 'comments' 设为 "n:),n:>",则以
">) >" 开始的行会被当作注释。
b 在 {string} 之后必须有空白字符 (包括 <Space>、<Tab> 或 <EOL>)。
f 仅在首行出现的注释字符串。下一行不需要注释字符串,但需要保留相同的缩进
(例如,项目符号列表 (bullet-list))。
s 三段式注释的起始字符串
m 三段式注释的中间字符串
e 三段式注释的结束字符串
l 左对齐。和 's' 或 'e' 配合使用。三段式注释的起始或结束字符串的最左侧字
符会和中间字符串的最左侧字符对齐。这是缺省值,可以省略。详情见下。
r 右对齐。同上,但对齐最右侧字符而非最左侧字符。详情见下。
O 对 "O" 命令不识别此类注释。
x 允许自动插入中间注释字符串后,通过输入结束字符串的末字符作为新行的首个
操作来结束三段式注释。详情见下。
{digits}
和 's' 或 'e' 配合使用: 为自动插入的中间或结束字符串增加 {digit} 单位
的偏移量前缀。偏移量从左对齐位置开始计算。详情见下。
-{digits}
和 {digits} 类似,但减少缩进而非增加缩进。仅当开始或结束部分有可移除的
缩进量时才有效。
当字符串不包含 'f'、's'、'm' 或 'e' 中任何一个标志位时,Vim 假定该注释字符串在
每行开头重复出现。{flags} 字段可以为空。
在 {string} 之前或之后的任何空白字符都属于 {string} 的一部分,所以不要随便在开
头或结尾留出空白,除非这些空白的确是注释字符串的必需部分。
当某个注释字符串是另一个注释字符串的一部分时,必须将更长的字符串写在前面。例
如,要同时包含 "-" 和 "->",可用
:set comments=f:->,f:-
三段式注释必须按顺序完整给出起始、中间和结束三部分,而且中间不能间杂其他部分。
三段式 C 语言注释的示例
sr:/*,mb:*,ex:*/
为了避免将 "*ptr" 识别为注释,中间字符串包含了 'b' 标志位。对于三段式注释,Vim
会检查起始和中间字符串之后的文本中是否包含结束字符串。如果找到,下一行将不再识
别为注释。三段式注释的中间字符串是必需的,否则 Vim 无法识别中间行。
注意上述三段式注释定义里使用的 "x" 标志位。在 C 语言注释中按回车时,Vim 会自动
为新行插入中间字符串: " * "。要结束注释,只需在新行输入其他内容前键入 "/"。这
会把中间字符串替换成结束字符串,并应用其指定的对齐方式,只保留 " */"。省却了先
按退格键再输入完整的结束字符串的麻烦。
某行同时匹配三段式注释的中间和结束部分时,如果结束部分更长,优先使用结束部分。
这使得 C 风格注释可以正常工作,无需以空格结尾的中间部分。
一个使用对齐标志位的示例,突出注释 (也很像一个 1 字)。考虑下例:
:set comments=sr:/***,m:**,ex-2:******/
/***
**<--右对齐,来自 "r" 标志位
**
2 个单位偏移量,来自 "-2" 标志位-->**
******/
该例中,起始注释需要手动键入,然后按回车四次,最后输入 "/" 以结束注释。
以下是三段式注释的更多细节。有三个时间点会考虑对齐和偏移量相关的标志位: 在起始
注释后新开一行时、在注释未结束前新开一行时、以及自动结束三段式注释时。结束部分
的对齐标志位是反向生效的;结果是,"s" 和 "e" 使用相同对齐标志位 ("l" 和 "r")
时会使起始和结束部分拥有相同的缩进。每个注释部分只应使用一种对齐方式,但偏移量
会优先于 "r" 和 "l" 标志位。
打开 'cindent' 后,在很多情况下会覆盖对齐标志位。使用 gq 或 = 等其他方式格
式化也不会参考对齐标志位。要定义相同行为,可使用其他的格式化选项。需要注意的
是,'cindent' 虽然有基于上下文调整注释缩进的额外选项,但无法完整复制三段式注释
的缩进对齐方式。不过,'indentexpr' 能更好地处理三段式注释。
其它示例:
"b:*" 匹配 "*" 开头的行,但 "*" 后紧跟非空白字符的除外。这避免将指针
解引用操作 "*str" 被识别为注释。
"n:>" 匹配形如 ">"、">>"、">>>" 等开头的行。
"fb:-" 自动排版以 "- " 开头的项目符号列表。
本选项的缺省值为 "b:#"。这意味着 "#include" 开头的行不会被识别为注释,但以
"# define" 开头的行会。这是一种折中方案。
fo-table
'formatoptions' 选项用于控制 Vim 的内置文本排版规则。该选项是包含下列字符的字
符串。缺省值为 "tcq"。为便于阅读,选项字符间可用逗号分隔。
字符 在 'formatoptions' 里代表的含义
fo-t
t 依据 'textwidth' 自动断行普通文本。
fo-c
c 依据 'textwidth' 自动断行注释,并自动补全当前注释前缀。
fo-r
r 插入模式下按 <Enter> 后,自动补全当前注释前缀。
fo-o
o 普通模式下按 o 或者 O 新开一行时,自动补全当前注释前缀。如果在个别
位置不想要该前缀,可按 CTRL-U 快速删除。 i_CTRL-U
fo-/
/ 和 o 配合使用: 仅用于 // 注释前缀,仅当该前缀出现在一行开头时才会在
新行自动补全,该前缀出现在语句后方时不会。
fo-q
q 允许使用 gq 排版注释。
注意 排版不会影响空白行或只包含注释前缀的行。此类行或注释前缀发生变更
的位置,会被视作新段落起点。
fo-w
w 行尾空白指示当前段落会延续到下一行。而以非空白字符结尾的行会结束当前段
落。
fo-a
a 对段落进行自动实时排版。新增或删除文本时,会即时重排段落。参见
auto-format 。
给出 'c' 标志位时,该设置只对能识别的注释有效。
fo-n
n 排版时,识别编号列表。'formatlistpat' 选项可用于识别不同种类的列表。列
表编号之后文本的缩进量,会延续到下一行。缺省模式为数值,后跟一个可选的
'.'、':'、')'、']' 或者 '}'。
注意 此功能需要同时置位 'autoindent'。不建议与 "2" 标志位一起使用,有
兼容性问题。
示例:
1. 第一项
回绕文字
2. 第二项
fo-2
2 排版段落时,段落其余行的缩进以段落第二行的缩进量为标准,而非第一行。适
用于第一行有特殊缩进需要的段落。注意 此功能需要同时置位 'autoindent'。
示例:
段落第一行
同一段落的第二行
第三行。
注释内同样生效,这里计算缩进量时会忽略注释前缀。
fo-v
v 插入模式下使用 Vi-兼容方式的自动断行: 仅在本次输入操作手动输入的空白字
符上才会断行 (注意: 这仍然不是 100% Vi 兼容。Vi 在这方面有些 "出人意料
的特性" (更准确地说是缺陷),因为它使用屏幕列而非实际列)。
fo-b
b 和 'v' 类似,但仅在回绕边界及之前位置输入空白字符时才会自动断行。如果
插入前该行已超出 'textwidth' 指定的行宽,或者在到达行宽之时未输入过空
白,Vim 不会自动断行。
fo-l
l 插入模式不断开长行: 插入模式开始时,如果该行已经超过 'textwidth',Vim
不会自动断行。
fo-m
m 允许在取值高于 255 的多字节字符处断行。适配亚洲文本的排版,因为此时每
个字符都是可单独断开的独立单位。注意 为了遵循中日韩换行规范,标点符号
(如冒号) 后也可断行。
fo-M
M 合并行时,不在多字节字符前后添加空格。优先于 'B' 标志位。
fo-B
B 合并行时,两个多字节字符之间不插入空格。有 'M' 标志位时无效。
fo-1
1 避免在单字母单词后断行。只要可能,优先在该单词前断行。
fo-]
] 严格遵循 'textwidth' 限制。除非受断行禁则
(line-break-prohibition rules) 约束,否则所有行不得超出设定宽度。主要
适配中日韩文本,且需要 'encoding' 为 "utf-8" 时才生效。
fo-j
j 合并多行内容时,自动删除多余注释前缀 (在合理前提下),合并为单行连续注
释。合并示例:
int i; // 列表中的
// 索引
结果是:
int i; // 列表中的索引
fo-p
p 不在句号后的单个空白字符处断行。和 'joinspaces' 和 cpo-J 互为补充,
配合双空格分隔句子的书写习惯。例如,假定 'textwidth' 设为 28:
Surely you're joking, Mr. Feynman!
结果是:
Surely you're joking,
Mr. Feynman!
而不是:
Surely you're joking, Mr.
Feynman!
通过 't' 和 'c' 的不同组合方式可指定 Vim 何时执行自动断行:
值 行为
"" 不自动排版 (可用 gq 进行手工排版)
"t" 自动排版普通文本,不排版注释
"c" 自动排版注释,不排版普通文本 (适合 C 程序)
"tc" 自动排版普通文本和注释
注意 'textwidth' 为 0 时,Vim 不会执行自动排版 (但仍会根据 'comments' 选项自动
插入注释前缀)。唯一例外是包含 'a' 标志位时,见 auto-format 。
注意 打开 'paste' 时,Vim 同样不会执行排版。
注意 即使 Vim 从不执行自动断行,也可将 'textwidth' 设为非零值,这对使用 gq
手动排版依然有用。
'comments' 选项包含 "/*"、"*" 和/或 "*/" 时,Vim 内置了一套逻辑,在处理这类注
释时会更智能。在 "/*" 或 "*/" 前后新开一行 ('formatoptions' 包含 'r' 或 'o')
时,会自动正确设置行首内容。排版或者自动断行时也会如此。在以 "/*" 或 "*" 开
头、且包含 "*/" 的行之后新开一行时,不会插入注释前缀,且新行的缩进取自注释起始
行。例如:
/* ~
* 任何注释。
*/ ~
这一行的缩进和上面注释的起始行相同。
这些功能非常实用,尤其适合与 :autocmd 命令协同使用,为不同文件类型提供不同的
排版设置。
若干示例:
适用于 C 代码 (只排版注释):
:set fo=croq
适用于邮件/新闻 (排版全部文本,但不通过 o 命令自动添加注释):
:set fo=tcrq
自动排版 auto-format autoformat
'formatoptions' 里包含 'a' 标志位时,新增或删除文本时,会即时重排段落。非常适
合纯文本段落编辑。以下为使用要点:
- 需要合理划分段落。最简单的方式是以空白行分隔段落。没有空白行时,可考虑采用
'w' 标志位,段落内除了末行外,其余行末尾都加上一个空格,以此标识段落延续。
- 可根据文件类型 filetype 设置不同的 'formatoptions'。要为单个文件单独设定,
也可用 modeline 。
- 将 'formatoptions' 设为 "aw2tq",可使文本以如下方式缩进:
bla bla foobar bla
bla foobar bla foobar bla
bla bla foobar bla
bla foobar bla bla foobar
- 如果只想自动排版注释,可加上 'c' 标志位。这适合于源代码编辑场景。
- 将 'textwidth' 设置为所需宽度。此值为零时,实际使用 79 列或当前屏幕宽度两者
的较小值。
注意事项:
- 如果段落划分不合理,局部编辑可能会触发所有相连的文本被自动排版。此时可考虑临
时关闭该标志位
:set fo-=a
- 启用 'w' 标志位 (行尾的空格代表段落延续) 时,用 dd 删除段落末行,会导致该
段落与下一段落自动合并。
- 文本修改会被记入撤销记录。排版也属于一种文本修改,因此,排版操作也会被记入撤
销记录。这可能导致相当大的内存开销。
- 超长段落和/或复杂缩进结构的排版操作,可能会相当耗时。
Vim 提供排序函数以及排序命令。排序函数可见: sort() 、 uniq() 。这里介绍排序命
令。
另见 :uniq 。
:sor :sort
:[range]sor[t][!] [b][f][i][l][n][o][r][u][x] [/{pattern}/]
对 [range] 范围内的所有行排序。范围省略时,为缓冲区所
有行排序。
带 [!] 则反向排序。
带 [i] 则忽略大小写。
:sort-l
带 [l] 时使用当前 locale 的排序规则排序。
实现细节: 字符串比较基于 strcoll()。可通过 :language
参看或设置当前用作排序规则的语言。
例如:
:language collate en_US.UTF-8
:%sort l
也可通过 v:collate 检查当前 locale。
按 locale 的排序通常会忽略大小写。
Mac 上此功能不能正常工作。
以下选项 [n][f][x][o][b] 互斥。
带 [n] 则按行中首个十进制数 (在 {pattern} 匹配项之后或
之内) 排序。数值包含不多于一个的前导 '-'。
带 [f] 则按行中指定的浮点数排序。浮点值通过在指定文本
(在 {pattern} 匹配项之后或之内) 上调用 str2float()
函数决定。{仅当 Vim 编译时加入浮点数支持才有效}
带 [x] 则按行中首个十六进制数 (在 {pattern} 匹配项之后
或之内) 排序。排序不考虑引导的 "0x" 或 "0X"。数值包含
不多于一个的前导 '-'。
带 [o] 则按行中首个八进制数 (在 {pattern} 匹配项之后或
之内) 排序。
带 [b] 则按行中首个二进制数 (在 {pattern} 匹配项之后或
之内) 排序。
:sort-u :sort-uniq
带 [u] (u 代表 unique 唯一) 则只保留重复行序列的首行
(带 [i] 时重复行的判定会忽略大小写)。
不带此标志位时,重复行序列会按其原有顺序保留。
注意 行首和行尾的空白差异会被视为不同行。
单纯想去重时,可用 :uniq 。
指定 /{pattern}/ 且不带 [r] 标志位时,会跳过匹配文本,
按匹配后的内容排序。
模式匹配考虑 'ignorecase',但忽略 'smartcase'。
可用任何非字母的字符代替斜杠作为定界符。
示例,按第二个字段 (以逗号分隔) 排序:
:sort /[^,]*,/
按虚拟第 10 列上的文本排序 (从而忽略缩进使用制表还是空
格的区别):
:sort /.*\%10v/
按每行中首个数值排序,忽略之前的内容:
:sort /.\{-}\ze\d/
(说明: ".\{-}" 匹配任何文本,"\ze" 设置匹配结束位置,
\d 匹配单个数位。)
带 [r] 则在匹配 {pattern} 的文本上进行排序,而不是如上
所述的按其后续文本排序。
示例,按每行前三个字母排序:
:sort /\a\a\a/ r
使用 {pattern} 时,未匹配 {pattern} 的行会按其原有顺序
保留,但与有匹配 {pattern} 的行分开。使用反向排序时,
无匹配行会以反序出现,并排在已排序行之后。否则,无匹配
行会以原有顺序出现,并排在已排序行之前。
{pattern} 为空 (如 //) 时,使用最近使用的搜索模式。可
先测试好模式,再执行本命令。
注意 :sort 和 :global 一起使用无法只对匹配行排序,这种用法基本没有意义。
除非使用 l 标志位,否则 :sort 默认不使用当前系统的 locale。不过,Vim 执行的
是 "稳定" 排序。
排序过程可以被中断,但如果中断时机太晚,最后可能会出现行重复的情况。这取决于系
统库函数的实现。
Vim 提供去重函数和去重命令。去重函数可见: uniq() 。这里介绍去重命令。
另见 :sort-uniq 。
:uni :uniq
:[range]uni[q][!] [i][l][r][u] [/{pattern}/]
删除 [range] 范围内相邻的重复行。范围省略时,处理缓冲
区所有行。
带 [i] 则比较时忽略大小写。
带 [l] 时使用当前 locale 的排序规则进行比较。
详见 :sort-l 。
带 [r] 则仅根据匹配 {pattern} 的文本进行比较,而非按其
后续文本。
带 [u] 则只保留不重复的行 (即后面没有紧跟重复内容的
行)。
带 [!] 则只保留后面紧跟重复内容的行。
如果同时给出 [!] 和 [u],[!] 优先,忽略 [u]。
指定 /{pattern}/ 且不带 [r] 标志位时,会跳过匹配文本,
按匹配后的内容进行比较。
模式匹配考虑 'ignorecase',但忽略 'smartcase'。
可用任何非字母的字符代替斜杠作为定界符。
示例,按第二个字段 (以逗号分隔) 去重:
:uniq /[^,]*,/
要忽略前 5 个字符,只保留不重复行:
:uniq u /.\{5}/
{pattern} 为空 (如 //) 时,使用最近使用的搜索模式。
注意 行首和行尾的空白差异会被视为不同行。
要删除出现在任何位置的重复行 (无论是否相邻),可用
:sort-u 或外部工具。
vim:tw=78:ts=8:noet:ft=help:norl: