安装
下载windows安装包, 最新版在这里
下载中文帮助安装包, 最新版在这里
安装vim-plug插件, 原文件在这里, 下载plug.vim,然后把它放到vim安装路径的autoload目录下
VIM简介
VIM是一种信仰。
对我来说vi是禅, 使用vi就是使用禅。每个命令都是心印,这对用户来说是深奥的,对未入门者来说是无法了解的。每次使用它你都能发现真理。 --Satish Reddy
商业化产品可能是有用的, 但最好的东西往往是免费的, 空气, 水, vim
高效编辑的原则
形成过程
- 自省, 找出重复/低效的部分
- 寻找solution
- 使之成为习惯
7 Habits
- 他们能做事主动。 (“积极主动”)
- 他们能关注目标。 (“以终为始”)
- 他们能确定要务。 (“要事第一”)
- 他们能与人共赢。 (“双赢思维”)
- 他们能与人沟通交流。 (“知彼解己”)
- 他们能与人合作。 (“统合综效”)
- 他们能反省自己并弥补不足。 (“自我更新”)
区分学习和使用
- 学习是投入,使用是产出
- 学习是投资,使用是收益
- 不要第二次寻找同一问题的解决方案(DRY)
拿来主义
- 选择性收集技巧, 有用的 VS 对你有用的
- 避免收集对自己无用的高度特殊化的技巧
不要为用不到的功能买单
- 不要提前买单
- 技能的投入产出比
- 遗忘曲线
- 打磨技艺持续前进
不断提高
- 理解而非记忆
- 培植而非收藏
- 精心经营个人化功能子集
- 全面了解,不要浅尝辄止
态度
- 学而不用,积而不发
- 了解工具实际被设计能做的事, 而不是你希望它能做的事.
高效与否, 操之在你
- 工具只会跟使用者一样好
开放态度, 不要拒绝其它工具
- 手持锤子,满世界都是钉子
第一课
学会自己搜索答案
第二课
完成vimtutor
vimtutor位于vim安装目录里,一个可执行程序(脚本)
它大约需要20分钟
第三课 Motion
通用
h/l/k/j
G/{num}G/gg/:{num}
%
gk/gj
0/^/$
f{char}/F{char}/t{char}/T{char}/;/,
: t=till=find-1-/+/_
练习
To err is human. To really foul up you need a computer.
<------------ ------------->
Th tn
单词级移动
key | action |
---|---|
w 或 W | 移动到下一单词的开头 |
b 或 B | 移动到上一单词的开头 |
e 或 E | 移动到光标所在单词的末尾 |
ge b w e
<- <- ---> --->
This is-a line, with special/separated/words (and some more).
<----- <----- --------------------> ----->
gE B W E
ge b w e
大范围移动
key | action |
---|---|
% | 移动光标到括号左半部分( 包括(、{、[ )对应右半匹配部分( )、}、] ) |
} | 移动光标到当前段落的末尾 |
{ | 移到光标到当前段落的开头 |
H | 移动光标到屏幕的第一行 |
M | 移动光标到屏幕的中间一行 |
L | 移动光标到屏幕的最后一行 |
Ctrl + f | 向前滚动一页 |
Ctrl + b | 向后滚动一页 |
Ctrl + u | 向前滚动半页 |
Ctrl + d | 向后滚动半页 |
/<string> | 向前查找, 结合n/N可以重复向前向后查找同一字符 |
?<string> | 向后查找, 可以结合n/N |
关于查找
.*[]^%/\?~$
有特殊含义,如果要查找它们,在在前面加上\
.- 可以用
:set ic
或:set noic
来忽略或不忽略大小写 - 输入
/
或?
后可以用<Up>或<Down>来查找历史记录。 - 可以在单词上用
*
或#
来向前或向后查找光标下单词 - 如果要精确匹配, 用
\<
或\>
来精确匹配开头或结尾,两者可以同时使用,如/\<the\>
,这样three不会被匹配
位置标记
key | desciption |
---|---|
m{a-zA-Z} | 把位置标记 {a-zA-Z} 设在当前光标位置 (不移动光标,这不是动作命令)。 |
g'{mark} | 跳转到指定的位置标记 {mark},但在当前缓冲区内跳转时,不改变跳转表。 |
:marks | 列出所有的位置标记 (这不是动作命令),第一列的编号为零。 |
标志说明
mark | description |
---|---|
'a - 'z | 小写位置标记,在每个文件内有效。 |
'A - 'Z | 大写位置标记,也叫做文件标记,在文件间都有效。 |
'0 - '9 | 数字位置标记,在 .viminfo 文件里设置。 |
跳转
key | action |
---|---|
CTRL-O | 转到跳转表里第 [count] 个较旧的光标位置 (不是动作命令)。 |
CTRL-I | 转到跳转表里第 [count] 个较新的光标位置 (不是动作命令)。 |
:ju[mps] | 打出跳转表 (不是动作命令)。 |
:cle[arjumps] | 清除当前窗口的跳转表。 |
编辑命令
<number> <operator> <text object or motion>
<次数> <操作符> <文本对象或移动命令>
操作符
key | action |
---|---|
c | 修改 (change) |
d | 删除 (delete) |
y | 抽出 (yank) 到寄存器 (不改变文本) |
~ | 变换大小写 (只有当 'tildeop' 置位时有效) |
g~ | 变换大小写 |
gu | 变为小写 |
gU | 变为大写 |
! | 通过外部程序过滤 |
= | 通过 'equalprg' (若为空,C-indenting) 过滤 |
gq | 文本排版 |
gw | 文本排版,不移动光标 |
> | 右移 |
< | 左移 |
zf | 定义折叠 |
高级技巧: 可以用":"命令定义一个动作, 例如d:call search("f")<CR>
, 如果该命令多于一行,则不能用"."重复。
面向对象类型
一共三种: 字符/行/列
key | type |
---|---|
v | 在操作符后和动作命令之前应用: 即使该动作是面向行的,也强制该操作面向字符。 |
V | 在操作符后和动作命令之前应用: 即使该动作是面向字符的,也强制该操作面向行。 |
CTRL-V | 在操作符后和动作命令之前应用: 强制该动作面向列块。 |
练习: dj
, dvj
, d<C-V>j
对象定义
- word: 一个单词由字符、数字和下划线序列或者其他的非空白字符的序列组成。单词间可以空白
字符 (空格、制表、换行) 分隔。这一规则可以用 'iskeyword' 选项改变。空行也被认
作单词。 - WORD: 一个字串由非空白字符序列组成。字串以空白分隔。空行也被认作字串。
- sentence: 一个句子以 '.'、'!' 或者 '?' 结尾并紧随着一个换行符、空格或者制表符。标点和空
白字符之间可以出现任何数量的闭括号和引号: ')'、']'、'"' 和 '''。另,段落和小节
的边界也视为句子的边界。 - paragraph: 一个段落从空行或某一个段落宏命令开始,段落宏由 'paragraphs' 选项里成对出现的字
符所定义。它的缺省值为 "IPLPPPQPP TPHPLIPpLpItpplpipbp",也就是宏 ".IP"、".LP"
等 (这些是 nroff 宏,所以句号一定要出现在第一列)。小节边界也被视为段落边界。
注意 空白行 (只包含空白) 不是 段落边界。 - section: 一个小节从首列出现的换页符 (<C-L>) 或某一个小节宏命令开始。小节宏由 'sections'
选项里成对出现的字符所定义。它的缺省值是 "SHNHH HUnhsh",也就是说小节可以从如
下的 nroff 宏开始: ".SH"、".NH"、".H"、".HU"、".nh" 和 ".sh"。
文本对象
key | description | ||
---|---|---|---|
aw | "一个单词",选择 [count] 个单词 (见 | word | )。包括开头或拖尾的空白,但不单独计算。在可视面向行的模式下,"aw" 切换到可视面向字符的模式。 |
iw | "内含单词",选择 [count] 个单词 (见 | word | )。单词之间的空白也被算为一个单词。在可视面向行的模式下,"iw" 切换到可视面向字符的模式。 |
aW | "一个字串",选择 [count] 个字串 (见 | WORD | )。包括开头或拖尾的空白,但不单独计算。在可视面向行的模式下,"aW" 切换到可视面向字符的模式。 |
iW | "内含字串",选择 [count] 个字串 (见 | WORD | )。字串之间的空白也被算为一个字串。在可视面向行的模式下,"iW" 切换到可视面向字符的模式。 |
as | "一个句子",选择 [count] 个句子 (见 | sentence | )。可视模式下它切换为面向字符的模式。 |
is | "内含句子",选择 [count] 个句子 (见 | sentence | )。可视模式下它切换为面向字符的模式。 |
ap | "一个段落",选择 [count] 个段落 (见 | paragraph | )。特例: 空白行 (只包含空白的行) 也被视为段落边界。可视模式下它切换为面向行的模式。 |
ip | "内含段落",选择 [count] 个段落 (见 | paragraph | )。特例: 空白行 (只包含空白的行) 也被视为段落边界。可视模式下它切换为面向行的模式。 |
a( 或ab | "一个()块",包括'(' 和 ')' | ||
i( 或ib | "一个()块",不包括'(' 和 ')' | ||
a{ 或a{ | "一个{}块",包括'{' 和 '}' | ||
i{ 或i{ | "一个{}块",不包括'{' 和 '}' | ||
a" 或a' 或a\ ` | "一个引号字符串", 包括引号 | ||
i" 或i' 或i\ ` | "一个引号字符串", 不包括引号 |
常见命令
key | actions |
---|---|
x | 删除光标下的字符 ("dl" 的缩写) |
X | 删除光标前的字符 ("dh" 的缩写) |
D | 从当前位置删除到行尾 ("d$" 的缩写) |
dw | 从当前位置删除到下一个单词开头 |
db | 从当前位置删除到前一个单词的开头 |
diw | 删除光标上的单词 (不包括空白字符) |
daw | 删除光标上的单词 (包括空白字符) |
dG | 删除到文件末 |
dgg | 删除到文件首 |
上面的d可以改成c或y
插入和替换
插入模式命令
key | action |
---|---|
a | 在光标后附加文本 [count] 次。如果光标在空行的第一列,启动插入模式。但在置位了 'virtualedit' 以后就不是! |
A | 在行尾附加文本 [count] 次。 |
i | 在光标前插入文本 [count] 次。在插入模式里使用 CTRL-O 的时候,i_CTRL-O 不支持计数。 |
I | 在本行第一个非空白字符之前插入文本 [count] 次。如果 'cpoptions' 里有 'H' 标志位而本行只有空白,在最后一个空白前插入。 |
gI | 在第一列插入文本 [count] 次。 |
gi | 在当前缓冲区最近一次插入模式停止的位置继续插入文本。该位置记在 '^ 位置标记里。如果标记在行末之后,和 "^i" 有所差异。该位置在插入/删除行时会自动修正。但_不_在插入/删除字符时被修正。使用 :keepjumps 命令修饰符时,不改变 '^` 位置标记。 |
o | 在光标下方开启新行,并插入文本,重复 [count] 次。如果 'cpoptions' 里有 '#' 标志位,忽略计数。 |
O | 在光标上方开启新行,并插入文本,重复 [count] 次。如果 'cpoptions' 里有 '#' 标志位,忽略计数。 |
用<Esc>或<Ctrl-C>退出插入模式
Ex插入命令
key | Actions |
---|---|
:{range}a[ppend][!] | 在指定行下方添加若干行。如果没有给出 {range},文本会在当前行之后插入。加入 [!] 切换此命令执行时的 'autoindent'。 |
:{range}i[nsert][!] | 在指定行上方添加若干行。如果没有给出 {range},文本会在当前行之前插入。加入 [!] 切换此命令执行时的 'autoindent'。 |
这两个命令会继续要求行,直到你输入了只包含 "." 的一行。小心反斜杠开始的行,见 line-continuation
。
Ex 模式 (见 -e
) 下,行尾的反斜杠可用来插入 NUL 字符。所以要使一行以反斜杠结尾,用两个反斜杠。也就是说仅在行尾情况下,反斜杠数目减半。
注意: 这些命令不能和 :global
或 :vglobal
一起使用。":append" 和 ":insert" 在 ":if" 和 ":endif"、":for" 和 ":endfor" 还有 ":while" 和 ":endwhile" 之间不能很好的工作。
插入文件
key | action |
---|---|
:r[ead] [++opt] [name] | 在光标下方插入文件 [name] (缺省: 当前文件)。 |
:{range}r[ead] [++opt] [name] | 在指定行下方插入文件 [name] (缺省: 当前文件)。 |
:[range]r[ead] [++opt] !{cmd} | 执行 {cmd} 并把它的标准输出插入到光标下方。临时文件会建立来保存命令输出的结果,并被读到缓冲区里。'shellredir' 用来保存命令的输出结果,它可以设置是否包含标准错误的输出。 |
插入模式下的一些快捷键
key | action |
---|---|
<Esc> 或 CTRL-[ | 结束插入或替换模式,回到普通模式。结束缩写。 |
CTRL-C | 退出插入模式,回到普通模式。不检查缩写。不激活 InsertLeave 自动命令事件。 |
CTRL-@ | 插入最近插入的文本,并停止插入。 |
CTRL-A | 插入最近插入的文本。 |
<BS> 或 CTRL-H | 删除光标前的字符 。 |
<Del> | 删除光标下的字符。如果光标在行尾,并且 'backspace' 选项包括 "eol",删除 <EOL> ;下一行就此附加于当前行之后。如果你的 <Del> 键不正确,见 :fixdel。 |
CTRL-W | 删除光标前的单词 |
CTRL-U | 删除当前行上光标前的所有输入字符。 |
<Tab> 或 CTRL-I | 插入制表。如果打开 'expandtab' 选项,等价数目的空格被插入 也可使用 CTRL-Q <Tab> 。 |
<NL> 或 CTRL-J | 开始新行。 |
<CR> 或 CTRL-M | 开始新行。 |
CTRL-K {char1} [char2] | 输入二合字母 (见digraphs)。当 {char1} 为特殊字符时,该键的键码以 <> 形式插入。例如字符串 <S-Space> 可以这样输入: <C-K><S-Space> (两个键)。两个键都不考虑映射。 |
CTRL-N | 查找下一个关键字 (见 i_CTRL-N)。 |
CTRL-P | 查找上一个关键字 (见 i_CTRL-P)。 |
CTRL-T | 在当前行开始处插入一个 shiftwidth 的缩进。缩进总是取整到 'shiftwidth' 的倍数 (这是 vi 兼容的)。 |
CTRL-D | 在当前行开始处删除一个 shiftwidth 的缩进。缩进总是取整到 'shiftwidth' 的倍数 (这是 vi 兼容的)。 |
0 CTRL-D | 删除所有当前行的缩进。 |
^ CTRL-D | 删除当前行的所有缩进。缩进在下一行上恢复。这可以用于插入卷标。 |
CTRL-V | 如果下一个是非数字,按本义插入。对特殊键而言,插入其终端代码。CTRL-V 之后紧接着输入的字符不经过映射。注意: 当 CTRL-V 被映射时 (例如,用来粘贴文本),你可能经常需要使用 CTRL-Q 来代替 |
CTRL-SHIFT-V | 与 CTRL-V 类似,除非激活了 modifyOtherKeys,此时插入带修饰符的键的转义序列。 |
CTRL-Q | 等同于 CTRL-V。 |
CTRL-X | 进入 CTRL-X 模式,一个子模式。那里你可以给出命令来补全单词或者滚动窗口。见 i_CTRL-X 和 ins-completion 。 |
CTRL-E | 插入光标下面的字符。 |
CTRL-Y | 插入光标上面的字符。注意 CTRL-E 和 CTRL-Y 不使用 'textwidth',从而可以从长行里复制字符。 |
CTRL-] | 切换缩写,不插入字符。 |
<Insert> | 切换插入和替换模式。 |
插入寄存器内容
CTRL-R {register}
用于插入寄存器内容,在输入CTRL-R之后会有"
显示出来,这时你需要输入寄存器名字
register | Usage |
---|---|
" | 无名寄存器,包含最近删除或抽出的文本 |
% | 当前文件名 |
# | 轮换文件名 |
* | 剪贴板内容 (X11: 主选择) |
+ | 剪贴板内容 |
/ | 最近的搜索模式 |
: | 最近的命令行 |
. | 最近插入的文本 |
- | 最近的行内 (少于一行) 删除 |
= | 表达式寄存器;你会被提示输入一个表达式 (见expression) |
CTRL-R {register}
还有几个变种:
CTRL-R CTRL-R {register}
: 文本按本义插入,这意味着如果寄存器包含 <BS> 这样的字符,结果会不同。例如,如果寄存器包含 "ab^Hc":CTRL-R a
产生 "ac"。CTRL-R CTRL-R a
产生 "ab^Hc"。CTRL-R CTRL-O {register}
: 按本义插入寄存器内容,并且不进行自动缩进。CTRL-R CTRL-P {register}
: 按本义插入寄存器内容,修正缩进
复制并移动
keys | Usage | ||
---|---|---|---|
"{a-zA-Z0-9.%#:-"} | 指定下次的删除、抽出和放置命令使用的寄存器 {a-zA-Z0-9.%#:-"} (大写字符使得删除和抽出命令附加到该寄存器) ({.%#:} 只能用于放置命令)。 | ||
["x]y{motion} | 抽出 {motion} 跨越的文本 [到寄存器 x]。如果没有字符被抽出 (例如,在第一列执行 "y0") 并且 'cpoptions' 里包括 'E' 标志位,这是一个错误。 | ||
["x]yy | 抽出 [count] 行 [到寄存器 x] | linewise | 行动作。 |
["x]Y | 抽出 [count] 行 [到寄存器 x] (等同于 yy, | linewise | 行动作)。如果你想要 "Y" 执行从光标到行尾的操作 (更合乎逻辑,但是与 Vi 不兼容),用 ":map Y y$"。 |
{Visual}["x]y | 抽出高亮文本 [到寄存器 x] (关于 {Visual} 见 | Visual-mode | )。 |
{Visual}["x]Y | 抽出高亮行 [到寄存器 x] (关于 {Visual} 见 | Visual-mode | )。 |
["x]p | 放置文本 [从寄存器 x] 在光标之后 [count] 次。 | ||
["x]<MiddleMouse> | 从一个寄存器放置文本在光标之前 [count] 次。除非另外指定,否则用 "* 寄存器。光标停留在新文本的尾部。 | ||
["x]gp | 如同 "p",但光标停留在新文本之后。 | ||
["x]gP | 如同 "P",但光标停留在新文本之后。 |
Ex Command | Usage | ||
---|---|---|---|
:reg[isters] | 显示所有编号和命名寄存器的类型和内容。但不列出用于 :redir 目的地的寄存器。类型可以是以下之一: "c" 用于 characterwise 文本; "l" 用于 linewise 文本; "b" 用于 blockwise-visual 文本 | ||
:reg[isters] {arg} | 显示 {arg} 里提到的编号和命名寄存器的内容。例如: :reg 1a | ||
:di[splay] [arg] | 和 :registers 相同。 | ||
:[range]y[ank] [x] | 抽出 [range] 所指定的行 [到寄存器 x]。仅当包含 | +clipboard | 特性时才可以抽出到 "* 或 "+ 寄存器。 |
:[range]y[ank] [x] {count} | 从 [range] 的最后一行开始 (缺省: 当前行 | cmdline-ranges | ) 抽出 {count} 行 [到寄存器 x]。 |
:[line]pu[t] [x] | 放置文本 [从寄存器 x] 在行号 [line] (缺省为当前行) 之后。 | ||
:[line]pu[t]! [x] | 放置文本 [从寄存器 x] 在行号 [line] (缺省为当前行) 之前。 | ||
:[range]co[py] {address} | 把 [range] 指定的行复制到 {address} 给出的行之下。 | ||
:[range]m[ove] {address} | 把 [range] 指定的行移动到 {address} 给出的行之下。 |
put
总是 linewise 行动作,因而这个命令可以用来把抽出的块放置在新行上。寄存器也可以是 '=',跟随一个可选的表达式。表达式继续到该命令结束为止。你需要在 '|' 和 '"' 字符前加上反斜杠不让它们终止你的命令行。例如: :put ='path' . \",/test\"
;如果 '=' 之后没有表达式,Vim 使用前一个表达式。用 :dis =
你可以看到它。
上面这些命令也可以用于global命令, 详细列表查看help ex-cmd-index
寄存器类型:
- 无名寄存器 ""
用 "d"、"c"、"s"、"x" 等命令删除或者用 "y" 等抽出命令复制的文本都被 Vim 用来填
充该寄存器 - 10 个编号寄存器 "0 到 "9
Vim 把抽出和删除命令的文本保存在这些寄存器里。 - 行内删除寄存器 "-
该寄存器保存删除不到一行内容的命令的文本 - 26 个命名的寄存器 "a 到 "z 或者 "A 到 "Z
Vim 只有在你指定的时候才使用这些寄存器。指定为小写字母时替换原来的内容,指定为大写字母时附加到原来的内容。 - 三个只读寄存器 ":、". 和 "%
". 包含最近插入的文本
"% 包含当前文件名
“: 包含最近执行过的命令行。 - 轮换缓冲区寄存器 "#
包含当前窗口buf文件名 - 表达式寄存器 "=
其实并没有这么一个寄存器,这是可读写的 - 选择和拖放寄存器 "*、"+ 和 "~
用这些寄存器来保存和取得 GUI 界面选择的文本。 只读的 "~ 寄存器保存最近一次拖放操作放下的文本 - 黑洞寄存器寄存器 "_
- 最近搜索模式寄存器 "/
常用选项
组 | 选项 | 描述 |
---|---|---|
用法 | :set all | 显示所有选项和设置; |
:set | 显示当前设置的所有选项; | |
:set num? | 显示num选项的当前设置;num可以换成其他选项; | |
:set num | 打开选项与关闭选项; | |
:set nonum | num可以换成其他选项; | |
num/nonum | 是/否显示行号; | |
wrap/nowrap | 是(默认)/否自动换行; | |
wrapmargin=n | 设置右边界的值,当输入时到达右边界,并遇到空格时,会自动插入换行; | |
aw/noaw | 临时转入shell或使用":n"编辑其他文件时,是/否自动保存当前文件已做的修改; | |
flash/noflash | 在出错处使用闪烁提醒/使用呜叫提醒; | |
缩进 | ai/noai | autoindent是/否使用自动缩进方式,新行与前面的行保持—致的缩进; |
smartindent | smartindent/nosmartindent:是否使用能识别类C语法的智能缩进方式; | |
cindent | cindent/nocindent:是/否使用cindent缩进方式; | |
indentexpr | indentexpr/noindentexpr:是/否使用indentexpr缩进方式; | |
indenttype= | 缩进方式:autoindent、smartindent、cindent、indentexpr(同上); | |
shiftwidth=n | 自动缩进字符数; | |
tabstop=n | 将TAB键的宽度设置为n个宁符宽度,默认为8; | |
编码 | encoding= | 设置vim内部使用的编码字符集;如:prc; |
fileencoding= | 设置当前编辑的文件的字符编码方式;如:utf-8; | |
fileencodings= | 设置vim自动探测fileencoding的顺序列表;如:"ucs-bom,utf-8,latin1"; | |
termencoding= | vim工作的终端的编码方式;如:utf-8; | |
ambiwidth= | 设置汉字所占字符宽度;如:double; | |
搜索 | ic/noic | 搜索时忽赂大小写/不忽略大小写(默认); |
wrapscan | 在搜索时到达文件尾后是/否跳文件头继续搜索; | |
incsearch | incsearch/noincsearch:输入搜索关键字时,是/否(默认)自动高亮匹配的字符; | |
hlsearch | hlsearch/nohlsearch:搜索后,是/否(默认)保留匹配字符的高亮显示 | |
编程 | syntax= | on/off:是/否显示语法高亮; |
保存 | ro/noro | 是/否只读模式,只读模式写只能通过强制方式":w!"写入,否则无法写入; |
history=n | history记录的行数,默认100个历史记录; | |
file | filetype on | 侦测文件类型; |
filetype plugin on | 载入文件类型插件; | |
filetype indent on | 为特定文件类型载入相关缩进文件; | |
report=n | 复制或者删除了多少行时显示提示信息,默认为2; | |
laststatus=0,1,2 | 是否显示状态栏,0:不显示,1:需要时间显示,2:总是显示; | |
list/nolist | 是/否将tab、换行符使用替代字符显示(^I、$); | |
shell=path | 设置vim执行外部命令时使用的shell路径,如:/bin/bash; | |
showmatch | 设置输入右半边括号时,是/否(默认)提示所对应的左半边括号; | |
showmode | 设置是(默认)/否在窗口左下角显示当前的模式:插入、替换等模式; | |
compatible | 除非.vimrc文件存在,默认vim会尝试采用vi兼容的模式; |
正则表达式
- 表示目标字符的元字符
元字符 | 说明 |
---|---|
. | 匹配任意字符 |
[abc] | 匹配方括号中的任意一个字符,可用-表示字符范围。如[a-z0-9]匹配小写字母和数字 |
[^abc] | 匹配除方括号中字符之外的任意字符 |
\d | 匹配阿拉伯数字,等同于[0-9] |
\D | 匹配阿拉伯数字之外的任意字符,等同于1 |
\x | 匹配十六进制数字,等同于[0-9A-Fa-f] |
\X | 匹配十六进制数字之外的任意字符,等同于2 |
\l | 匹配[a-z] |
\L | 匹配3 |
\u | 匹配[A-Z] |
\U | 匹配4 |
\w | 匹配单词字母,等同于[0-9A-Za-z_] |
\W | 匹配单词字母之外的任意字符,等同于5 |
\t | 匹配<TAB> 字符 |
\s | 匹配空白字符,等同于[\t] |
\S | 匹配非空白字符,等同于6 |
- 需要转义的字符
元字符 | 说明 |
---|---|
\* | 匹配* 字符 |
. | 匹配. 字符 |
\/ | 匹配 / 字符 |
\ | 匹配 \ 字符 |
\[ | 匹配 [ 字符 |
\] | 匹配 ] 字符 |
- 表示数量的元字符
元字符 | 说明 |
---|---|
* | 匹配0-任意个 |
\+ | 匹配1-任意个 |
\? | 匹配0-1个 |
\{n,m} | 匹配n-m个 |
\{n} | 匹配n个 |
\{n,} | 匹配n-任意个 |
\{,m} | 匹配0-m个 |
- 表示位置的元字符
元字符 | 说明 |
---|---|
$ | 匹配行尾 |
^ | 匹配行首 |
\< | 匹配单词词首 |
\> | 匹配单词词尾 |
- 表示子模式的元字符
用\(
和)
括起来的正则表达式,在后面使用时可以依次用\1
, \2
等变量来表示括号里的内容
- 表示非打印字符的元字符
元字符 | 说明 |
---|---|
\n | 表示匹配 一个换行符。 |
\r | 表示匹配 一个回车符。 |
\t | 表示匹配 一个制表符 ( Tab 键)。 |
\s | 表示匹配 任意一个空白字符,包括空格、制表符、换页符等。 |
\S | 表示匹配 任意一个非空白字符。 |
替换
substitue的缩写是s, 基本语法是: [range]substitue/search/replace/[flags] [count]
对 [range] 指定的行把 {pattern} 的匹配替代成 {string}。关于 {pattern},参见 |pattern|。{string} 可以是按本义出现的字符串,也可包含特殊字符。参见 |sub-replace-special|。如果不指定 [range] 和 [count],仅在当前行进行替代。如果指定 [count],在 [range] 最后一行开始的 [count] 行进行替代。如果不指定 [range] ,则从当前行开始。[count] 必须为正数。另见 |cmdline-ranges|。
- range
range
是同一个或多个被,
或;
分割的行限定符组成。当用;时, 光标位置会被设置为前一个行限定符确定的行值。
如果行限定符个数多于命令需要的数量,那么前面的限定符被忽略。
行号可以用下列符号:
符号 | 行号 |
---|---|
{number} | 行号 |
. | 当前行 |
$ | 文件的最后一行 |
% | 相当于 1,$ (整个文件) |
't | 标记 t 的位置 (小写) |
'T | 标记 T 的位置 (大写);如果标记存在于另一个文件中,则不能在范围里应用。 |
/{pattern}[/] | 下一个 匹配 {pattern} 的行 |
?{pattern}[?] | 前一个 匹配 {pattern} 的行 |
\/ | 下一个 与前次搜索模式匹配的行 |
\? | 前一个 与前次搜索模式匹配的行 |
\& | 下一个 与前次替代模式匹配的行 |
这些符号后面可以跟一个或多个+
或-
和一个可靠数字,如果数字省略,则认为是1/
和?
前面可能有另一个地址,那么查找就从那里开始。如果使用;
, 那么光标会移动
/pat1//pat2/
:不移动光标7;/pat2/
: 光标留在第7行
例子:
.+3
/that/+1
.,$
0;/that
1;/tath
- replace中的特殊字符
nomagic | 动作 |
---|---|
\& | 替代为完整的匹配 |
& | 替代为 & |
\0 | 替代为完整的匹配 |
\1 | 替代为匹配的第一个 () 里面的内容 |
\2 | 替代为匹配的第二个 () 里面的内容 |
.. | .. |
\9 | 替代为匹配的第九个 () 里面的内容 |
\~ | 替代为前一个 substitute 的替代字符串 |
~ | 替代为 ~ |
\u | 下一个字符成为大写 |
\U | 其后字符成为大写,直到 \E 出现 |
\l | 下一个字符成为小写 |
\L | 其后字符成为小写,直到 \E 出现 |
\e | 结束 \u、\U、\l 和 \L (注意: 不是 <Esc>!) |
\E | 结束 \u、\U、\l 和 \L |
<CR> | 把该行在此位置一分为二 (<CR> 以 CTRL-V <Enter> 方式输入) |
\r | 同上 |
\<CR> | 插入一个回车 (CTRL-M) (<CR> 以 CTRL-V <Enter> 方式输入) |
\n | 插入一个 <NL> (文件里的 <NUL>) (此处并不是换行) |
\b | 插入一个 <BS> |
\t | 插入一个 <Tab> |
\\ | 插入单个反斜杠 |
\x | 其中 x 是上面没提到的任何一个字符: 保留作将来的扩展 |
\1
,\2
等里的数字是基于模式里 \(
出现的顺序 (从左到右)。如果一个括号组匹配多次,最后一次的匹配被使用在 \1
,\2
等里。例如:
:s/\(\(a[a-d] \)*\)/\2/ # 修改 "aa ab x" 为 "ab x"
\2
对应 \(a[a-d] \)
。第一次匹配 "aa ",第二次匹配 "ab ", 最后一次匹配"ab "被用于\2
。
- Flags
Flags | Usage | |
---|---|---|
`& | 必须是首个使用的标志位,保留和上次substitue相同的标志位 | ` |
`c | ` 确认每个替代 | |
`e | ` 如果搜索不成功,不给出错误信息 | |
`g | ` 对行内所有匹配进行替代 | |
`i | ` 忽略模式的大小写 | |
`I | ` 不忽略模式大小写 | |
`n | ` 只报告匹配次数,不实际进行替代 | |
`p | ` 显示包含最后一次替代的行 | |
`# | ` 类似p, 且在前面加上行号 | |
`l | ` 类似p,但显示方式类似:list | |
`r | ` 如果匹配模式为空,优先使用上一次使用的搜索模式,之后再是上一次substitute或global使用的模式 |
- 示例
: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"
: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
多文件编辑
已经打开一个文件
- 打开一个新文件
edit[!] foo.txt
- 保存
write
- 打开一个新文件
- 打开多个文件
vim one.c two.c three.c
然后可以用:[num]next
,:wnext
,:[num]previous
,:wprevious
,:last
,:first
来切换 多文件跳转
可以用args one.c two.c three.c
来添加多个文件
然后可以用CTRL-^
来切换到上一个文件
有两个标记非常重要:`'"`: 你上次离开这个文件的位置 `'.`: 你最后一次修改文件的位置
可以用
m[a-zA-Z]
来标记文件, 然后用'[mark]
来跳转
还可以用CTRL-O
和CTRL-I
来在整个跳转序列中前后跳转
多窗口
分割窗口
可以直接用vim -O one.c two.c
来直接以分割方式打开多个文件-O
: 垂直分割-o
: 水平分割
如果已经打开文件,可以使用命令来打开/关闭窗口
:sp[lit] {file} 水平分屏
:new {file} 水平分屏
:sv[iew] {file} 水平分屏,以只读方式打开
:vs[plit] {file} 垂直分屏
:clo[se] 关闭当前窗口
:only 只显示当前窗口
上述命令都有快捷键, 共同前缀是: CTRL-W
Ctrl+w s 水平分割当前窗口
Ctrl+w v 垂直分割当前窗口
Ctrl+w q 关闭当前窗口
Ctrl+w n 打开一个新窗口(空文件)
Ctrl+w o 关闭除当前窗口之外的所有窗口
Ctrl+w T 移动当前窗口到新标签页
切换窗口
Ctrl+w h 切换到左边窗口
Ctrl+w j 切换到下边窗口
Ctrl+w k 切换到上边窗口
Ctrl+w l 切换到右边窗口
Ctrl+w w 遍历切换窗口
移动窗口
Ctrl+w H 向左移动当前窗口
Ctrl+w J 向下移动当前窗口
Ctrl+w K 向上移动当前窗口
Ctrl+w L 向右移动当前窗口
调整窗口大小
Ctrl+w + 增加窗口高度
Ctrl+w - 减小窗口高度
Ctrl+w = 统一窗口高度
映射
$$ <map command> <args> {lhs} {rhs} $$
command
Command | Normal | Visual | Operator Pending | Insert Only | Command Line | |
---|---|---|---|---|---|---|
命令 | 常规模式 | 可视化模式 | 运算符模式 | 插入模式 | 命令行模式 | |
:map | noremap | y | y | y | ||
:nmap | nnoremap | y | ||||
:vmap | vnoremap | y | ||||
:omap | onoremap | y | ||||
:map! | noremap! | y | y | |||
:imap | inoremap | y | ||||
:cmap | cnoremap | y |
Operator-pending模式,是指当你输入操作符(比如d)时,然后继续输入的移动步长和文本对象(dw)的状态
nore的含义是, 禁止对{rhs}再进行映射扫描,以防止嵌套和递归,通常用于重定义一个命令
args
<buffer>
,<nowait>
,<silent>
,<special>
、<script>
、<expr>
和 <unique>
可以按任意顺序使用。它们必须紧跟在命令的后边,而在其它任何参数的前边。
<buffer>
: 只作用于当前buffer<silent>
: 不回显命令<script>
: 只能使用<SID>
开关的脚本来映射{rhs}<unique>
: 如果映射或缩写的命令已存在,只命令失败<expr>
: 那个{rhs}是一个表达式,会用计算后的返回值代替{rhs}
强大的g
和v
:global
命令是 Vim 中一个更强大的命令 (之一)。它允许你找到一个匹配点并且在那里执行一个命令。它的一般形式是:
:[range]g/{pattern}/{command}
在每一匹配行上执行命令command. 这个命令只能是冒号命令, 普通模式命令不能在这里使用。如果需要,可以使用:normal
命令。
如果要查看可以使用的命令,可以help ex-cmd-index
。 如果要查看详细解释, 查看help 10.4
和 help multi-repeat
。
vglobal
相当于global!
, 两者可以组合使用, 如:g/found/v/notfound/{cmd}
利用global
我们可以把我们之前学的很多东西都串连起来,以完全一些非常奇妙的动作。
简单示例,
- 要删除所有空行:
:g/^$/d
- 要在含有always..begin的行后加上:label:
:g/always.*begin/s/$/ :label
exec和normal
execute
命令用来把一个字符串当作Vimscript命令执行。比如: :execute "rightbelow vsplit " . bufname("#")
normal
命令把我们的脚本跟日常的文本编辑按键结合起来, 比如: :normal ggdd
。 为了防止递归解析, 建议永远使用normal!
利用exec和normal的组合可以将动作变成可重复的命令, 并消除转义字符问题。比如: :execute "normal! mqA;\<esc>'q"
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。