目录

  • ​​引子​​
  • ​​vim的特点​​
  • ​​注意事项​​
  • ​​基本概念​​
  • ​​操作符​​
  • ​​动作​​
  • ​​操作符与动作命令语法​​
  • ​​vim操作符待决模式​​
  • ​​vim键盘速查表​​
  • ​​常用操作​​
  • ​​鼠标移动​​
  • ​​普通模式下操作​​
  • ​​复制y​​
  • ​​粘贴p​​
  • ​​删除d​​
  • ​​剪切​​
  • ​​查找​​
  • ​​正向查找​​
  • ​​反向查找​​
  • ​​配对括号的查找​​
  • ​​取消操作​​
  • ​​可视化模式​​
  • ​​可视化块模式​​
  • ​​命令模式​​
  • ​​替换命令​​
  • ​​常用操作​​
  • ​​其他操作​​
  • ​​参考​​

引子

研发线上使用最多的编辑器,就是vi。无论是最快查看某个文件内容,还是快速编辑某个文件,vi都能帮上忙。

软件世界貌似有一些非常长寿的东西,vi算是一个。本篇文章聚焦的是研发线上最常用的一些功能。至于安装插件,写一些脚本,那一般是在开发机上玩的;生产环境没有条件、也没有时间忍受你做这些增强。希望看完本文,能够对这款神器有一个大体印象。当然,熟练的使用还需要日常有意识的培养。

vim是vi的增强版,一般现代linux都不缺那几兆空间,所以预装的都是增强版,本文默认使用vim。

vim的特点

vim最大的贡献就是它的按键系统。这也是为什么chrome、idea、atom等编辑器都会提供一个vim mode。笔者见过很多资深的程序员,包括架构师,习惯使用方向键去控制光标的移动。这不能说不对,但这也抛弃了vim最大的精华所在,效率上低了一大截。坚持使用h、j、k、l,你会感谢你今天的纠正。大脑和手指真的是有记忆,当你用的足够多,这也就成了你约定俗成的设定。
vim另外一个特点就是带模式的。一共四种模式,我们不需要记忆,只需要使用例子去理解即可。

注意事项

不要使用vim打开大文件vim会一次性读取文件的所有内容到内存,容易造成宿主机内存溢出
打开文件前,可以使用du -h命令查看文件大小。一般,100MB以下为宜。

基本概念

Vim中有两个比较基础的概念:操作符(operator)和动作(motion)。

操作符

操作符是用于对文本进行删除或修改操作的命令。例如,d、~、gU 和 > 等都是 Vim 操作符。

命令     含义
c 修改
d 删除
y 复制到寄存器
g~ 反转大小写
gu 转换为小写
gU 转换为大写
> 增加缩进
< 减小缩进
= 自动缩进
! 使用外部程序过滤{motion}所跨越的行
gq 文本排版
g? ROT13 编码
zf 定义折叠
g@ 调用 'operatorfunc' 选项定义的函数

动作

动作 (用{motion}表示) 是指移动光标的命令或动作。

如经常使用的 h、j、k 和 l;
/ 和 ? 也是动作命令,
如 2?the 可以将光标移动到倒数第二个 “the” 出现的位置;
此外,w 表示移动至下一个单词的首部,
b 表示移动至当前单词的首部,
4j 表示下移四行,这些都是 Vim 动作命令。

操作符与动作命令语法

vim操作符与动作命令的结合形成了一种语法。

一个操作:由一个操作符,后面跟一个动作命令组成
动作命令出现在操作符之后,从而使得操作符作用于被该动作 所标识的文本。
即:一个动作可通过动作前和动作后的两个位置标识出一个文本区域,而标识出来的文本区域会用于执行操作符命令。

例如,由操作符和动作命令组成的 d{motion} 命令可以完成对一个字符 ( dl ) 或 一个完整单词 ( dw ) 的删除操作,删除操作作用的范围由具体的动作命令 motion 决定。

操作符和动作命令都可以搭配数字使用,用于完成多次相同的操作
如果动作命令包括一个次数而操作符之前也有一个的话,则两者相乘。
例如,2d3w 命令会删除6个单词,等价于 6dw 命令 或 d6w 命令。

Vim的语法有一条额外规则:当一个操作符命令被连续调用两次时,它会作用于当前行

所以 dd 删除当前行,而 >> 缩进当前行。
gU 命令是一种特殊情况,我们既可以用 gUgU ,也可以用简化版的 gUU 来使转换大写操作完整作用于当前行。

vim操作符待决模式

基于上述语法,引出了一种新的vim模式:
操作符待决模式 (operator pending mode),如果键入了操作符命令但还没有键入动作命令,则Vim正处于操作符待决模式下

例如,在执行命令 dw 时就会激活该模式。这一模式只在按 d 及 w 键之间的短暂时间间隔内存在。

如果把 Vim 想象成有限状态机,那么操作符待决模式就是一个只接受动作命令的状态。这个状态在调用操作符时被激活,然后什么也不做,直到输入一个动作命令,完成整个操作。

当操作符待决模式被激活时,我们可以像平常一样按 中止该操作,返回到普通模式。

命令 :omap 可以在待决模式时对字符进行映射,允许我们创建自定义的操作符及动作命令,从而扩充 Vim 的”词汇”。
只有Vim操作符才会激活操作符待决模式。
注:很多vim命令都通过两个或更多的按键来调用 (例如:zF、g&、[’、CTRL-W b),但在多数情况下,第一个按键只是第二个按键的前缀。这些命令不会激活操作符待决模式,相反,可以把它们当成命名空间,用来扩充可用命令的数目。

vim键盘速查表

经典的Vim键盘速查表中文介绍图以及各命令的详细介绍索引,按不同颜色区分Vim动作(motion)、Vim命令、Vim操作符(operator) 。

VIM学习二之linux下常用VIM技巧_字符串


说明如下所示:

Esc:返回到Vim的普通模式

~:大小写转换,即将当前光标所在的大写字符转为小写字符,或将当前小写字符转为大写字符

!:在 Vim 中执行外部命令,参考Vim执行shell命令。

@: 回放录制的宏操作,参考Vim宏录制与重复操作。

#:反向查找Vim当前光标所在单词,参考Vim搜索命令使用方法和技巧。

$:将Vim光标移动到当前所在行的行尾(实际行),参考Vim光标移动命令汇总。

%:找到本行的光标所在或其后的下一个项目,并跳转到它的匹配

^:将光标移动到当前行的第一个非空格字符(“软”行首)

&:等价于 😒,表示重复上次的 substitute 命令,参考Vim替换命令。

*:正向查找Vim当前光标所在单词,参考Vim搜索命令使用方法和技巧。

(:将光标移动到句首

):将光标移动到下一个句首

+:将光标移动到下一行行首,参考Ex命令偏移地址。

0:将光标移动到当前行行首 (“硬”行首,对应 ^)

-:将光标移动到上一行行首 (对应 +)

=:自动格式化,>>= 表示行首缩进,参考Vim自动缩进和tab键。

Q:切换到Ex模式
q:开始录制宏,参考Vim宏录制与重复操作。

W:将光标移动到下一个字串
w:将光标移动到下一个单词,关于 W 和 w 的区别,参考Vim单词和字串概念。

E:正向移动到当前字串 / 下一字串的结尾
e:正向移动到当前单词 / 下一单词的结尾

R:切换到替换模式
r:替换字符

T:反向移动到上一个目标所在之处的后一个字符上
t:正向移动到下一个目标字符所在之处的前一个字符上,参考Vim字符查找与光标快速移动。

Y:拷贝行
y:拷贝
U:撤销行内命令
u:撤销命令
I:到行首插入
i:插入模式
O:在当前行上一行插入
o:在当前行下一行插入
P:粘贴到前一行
p:粘贴到后一行
A:在行尾插入
a:在Vim当前光标后插入
S:删除行并插入
s:删除字符并插入,非常好用却被很多人忽略的命令
D:删除到当前行行尾
d:删除
F:行内字符反向查找
f:行内字符查找,参考Vim字符查找与光标快速移动。
G:将光标移动到文档末尾行
g:gg 将光标移动到文档首行,26gg 将光标移动到文档的第 26 行,gf 打开光标处的文件名
H:移动光标到屏幕顶行
h:光标往左移动
J:合并两行
j:光标往下移动
K:打开光标所在单词对应的Vim帮助文档
k:光标往上移动
L:移动光标到屏幕底行
l:光标往右移动
Z:ZZ 保存退出,ZQ 不保存退出
z:zz 移动光标所在行到屏幕顶端,zb 移动光标所在行到屏幕底端,zz 移动光标所在行到屏幕中间。
X:删除光标所在词的前一个字符,类似于word、notepad等编辑器中的退格 (Backspace)
x:删除字符
C:修改至行末;
c:修改当前光标下的字符,后面可以接一个移动范围,表示修改光标点到移动终点之间的内容并进入插入模式,参考Vim删除并进入插入模式命令c(change)。
V:进入行选择可视化模式;
v:进入字符选择可视化模式,参考vim可视化模式。
B:将光标移动到前一个字串;
b:将光标移动到前一个单词,参考vim单词和字串。
N:反向(往上)查找上一个目标串; ’
n:正向(往下)查找下一个目标串,参考vim查找。
M:将光标移动到屏幕中间行;
m:用于设置位置标注(vim mark),参考Vim位置标记mark详解。

常用操作

鼠标移动

光标,上下左右移动,当前光标向上向下移动n行;行首行尾移动;文件首文件尾移动;

j 向下
30j 向下移动30行
k 向上
h 向左
l 向右
0 到行首
^ 到行首第一个字符,如果前面有空格的话
$ 到行尾
gg 快速到文件头
G 快速到文件尾
100G 跳转到第100行

ps: 不建议在插入模式下进行光标移动,这很低效;

普通模式下操作

以下操作在普通模式下执行,连续按键;

复制y

复制一行/n行;复制一个单词;复制当前光标到当前行的指定位置(比如行尾,指定字符);

yy 复制一行
yw 复制从光标所在位置到当前【单词结束】部分的内容
10yy 向下复制10行
yw 复制光标开始的一个单词
y$ 复制光标到行尾
yfB 复制光标到第一个大写B中间的内容
y2fB 复制光标到第二个大写B中间的内容

注:yyp 操作可以实现复制一整行内容到当前所在行的下一行。

粘贴p

p 粘贴复制或剪切的内容
3p 将复制或剪切的内容粘贴三次

删除d

删除当前一行/往下的n行;删除一个单词;删除当前光标到当前行的指定位置;
许多改变文本的命令都由一个操作符和一个动作构成。

使用删除操作符 d 的删除命令的格式如下:
d motion
其中:
d - 删除操作符。
motion - 操作符的操作对象(在下面列出)。

一个简短的动作列表:
w - 从当前光标当前位置直到下一个单词起始处,不包括它的第一个字符。
e - 从当前光标当前位置直到单词末尾,包括最后一个字符。
$ - 从当前光标当前位置直到当前行末。

上面已经提到过删除操作符和动作的组合,您可以在组合中动作之前插入一个数字以
删除更多:
d number(数字) motion

dd 删除一行
200dd 表示从光标所在行开始删除后面的200行
dw 删除一个单词 (最喜欢啦)
d2w 删除2个单词
df” 删除到出现的第一个双引号
d2f" 删除当前光标到第二个出现双引号的位置
d$ 删除当前光标到行尾
d0 删除从光标所在位置到当前【行首】的内容
d$ 删除从光标所在位置到当前【行尾】的内容
dw/dW 删除从光标所在位置到当前【单词结束】部分的内容但不进入插入模式
db/dB 删除从光标所在位置到当前【单词开始】部分的内容但不进入插入模式

删除当前【句子】从光标位置开始到【句末】的内容:d)
删除当前【句子】从光标位置开始到【句首】的内容:d(
删除当前【段落】从光标位置开始到【段末】的内容:d}
删除当前【段落】从光标位置开始到【段首】的内容:d{
注:Vim命令中用 ( 和 ) 表示句子,{ 和 } 表示段落。

ps:
删除的内容会放到剪贴板,按p即可粘贴到其他地方
w (word)、b (back)命令用于光标移动
dW、dB 命令操作的单词是以空白字符 (空格、Tab) 分隔的字符串;

剪切

x 向剪切一个一个字符,如果是在行尾,则为向前剪切
3x 剪切三个
xp 非行尾交换两个字符,如从bs变成sb

查找

正向查找

在普通模式下,按下/直接进入查找,输入相应的字符串按确定即可
查找到字符串之后,如果存在多个,可以通过下面的操作进行跳转。

n 查找下一个匹配
N 查找上一个匹配
2n 查找下面第二个匹配
如果觉得跳来跳去晕头转向,可以在命令模式下输入set nu开启行号。

反向查找

如果您想逆向查找字符串,请使用 ? 代替 / 进行,然后输入字符串就可以反向查找。
n:向上查找;
N: 向下查找;

配对括号的查找

输入 % 可以查找配对的括号 )、]、}

把光标放在文本中的任何一个 (、[ 或 { 处。
接着按 % 字符。
此时光标的位置应当是在配对的括号处。
再次按 % 就可以跳回配对的第一个括号处。
提示:在程序调试时,这个功能用来查找不配对的括号是很有用的。

取消操作

在普通模式下,执行u(undo),则取消上一步操作。
输入 u 来撤消最后执行的命令,输入 U 来撤消对整行的修改
欲撤消以前的撤消命令,恢复以前的操作结果,请输入:CTRL-R

可视化模式

可视化模式是非常有用的一种模式,在普通模式下按v即可进入,此时可以看到-- VISUAL – 表示进入了可视化模式/视图模式

使用h、j、k、l进行漫游,选中相应的内容。然后进行操作;

范例如下所示:

选中一部分想要的内容,并删除

VIM学习二之linux下常用VIM技巧_字符串_02

可视化块模式

普通模式下按ctrl+v即可进入,此时可以看到-- VISUAL BLOCK – 表示进入了可视化块模式

在可视化块模式下,可以选择指定的块,然后对块的某一行操作,则会复制到指定块的所有行下

VIM学习二之linux下常用VIM技巧_vim_03


说明:

  1. 在命令行模式下,执行%s/$/");/g,在行尾追加数据);
  2. 按ESC进入普通模式,并使用gg回到行首
  3. 按ctrl+v进入可视化模式,然后按G到文件尾(选定块为行首到行尾)
  4. 不要理会编辑器反应,按I进入插入模式,输入list.add(" (在某一行进行操作,则复制到选定的块中所有行)
  5. 按ESC回到普通模式,可以发现以上输入已经在每一行生效了

命令模式

在普通模式下,输入:即可进入到命令行模式
命令行模式下,主要有替换操作、删除操作、移动光标到指定行、(保存)退出;

(1) 替换
:s/thee/the 只替换光标所在行的第一个匹配 串
:s/thee/the/g 替换光标所在行的全行的匹配串
:#,#s/old/new/g 替换指定行范围内的内容;其中 #,# 代表的是替换操作的起始行,结束行。
:%s/old/new/g 替换整个文件中的每个匹配串(%就是global的意思;最后的g应该是存在多个匹配时,是否全部替换)

(2)替换变形之追加
:%s/$/sth/ 在所有行的行尾追加sth

(3)替换变形之删除
:g/\^\s*$/d 删除所有的空行以及只有空格的行
:g/PATTERN/d 删除所有含有PATTERN的行
:%s/#.*//g 删除#及其之后的字符

(4)删除
:n,md 删除从n到m行;
:%d 删除所有行

(5)保存、退出
:w 保存当前编辑的文件
:w! 强制将当前编辑的文件保存:
:wq 保存当前文件并退出(write / quit)
:wqa 保存所有文件并退出
:q! 不保存,直接退出
:qa! 有多个文件被打开,同时退出

(6)另存为
:w FILENAME 将 Vim 当前打开的文件另存为新文件 FILENAME;
:saveas b.txt (缩写形式 :sav a.txt) 也可将当前打开的文件另存为新文件 a.txt。


(7)其他
:n 移动光标到第n行
:set nu 显示行号
:set nonu 取消行号显示
:set ignorecase 取消大小写,一般用于不区分大小写的查找;
:set ic 取消大小写(ignore case)
:set noic 禁用忽略大小写
:nohl 清除高亮(high light)
:f 显示当前的文件名

(8)说明:
光标所在行用 . 表示,文件的最后一行用 $ 表示,% 整个文件 (:1,$ 的简写形式)
:g global, 表示当前文件的所有行
:n,m 表示命令行模式下第n行到第m行;
s 表示替换(substitute)

你已经发现了,这大概就是针对编辑器窗口的sed命令

替换命令

替换命令:
substitute 命令的语法格式为:
:[range]s[ubstitute]/{pattern}/{string}/[flags]。
:[range]s/源字符串/目标字符串/[option],其中range和option字段都可以缺省不填。

range  表示搜索范围,默认表示当前行;
range字段值1,10表示从第1到第10行,
%表示整个文件(相当于1,$),
而.,$代表从当前行到文件末尾
s substitute的简写,表示替换
[flags] 表示可选的标志位,默认只对第一个匹配的字符进行替换.常用的包括 g、c、n、e 等。
标志位 g(global) :使得 substitute 命令可以修改一行内的所有匹配,而不仅仅是第一处匹配;
标志位 c(comfirm) :可以交互式的确认或拒绝每一处修改;
标志位 n :让 Vim 不执行替换操作,而只是统计和显示本次 substitute 命令匹配的个数;
标志位 e :专门用于屏蔽错误提示;
标志位 &: 用于指示 Vim 重用上一次 substitute 命令所用过的标志位。
注意:标志位g 看似为全局 (global) 的含义,容易让人误以为 g 标志位是用于实现在整个文件范围内进行替换操作,但实际上,g 仅表示当前一整行范围。由于 Vim 直接继承自 “行编辑器 ed”,对于行编辑器而言,全局的范围就是一行,这就是 g 标志位命令的由来。

常用操作

:1,$d     删除全部内容
:n,md 删除n到m行;
:g/\^\s*$/d 删除所有的空白行

其他操作

ggVG    普通模式下全选
u 普通模式下恢复更改
gU 光标处转大写
ggguG 整篇文章大写转化为小写
% 跳转到下一个匹配,如在<div>上按%,则跳转到相应的</div>
:e /tmp/a 在同一个编辑器内打开/tmp/a文件。同一个编辑器的缓冲区是剪贴板是共享的,可以方便在多个文件中复制;
bp 跳转到上一个缓冲区
bn 跳转到下一个缓冲区

参考

vim常用技巧:
https://mp.weixin.qq.com/s?__biz=MzA4MTc4NTUxNQ==&mid=2650518612&idx=1&sn=125c2cb9ee6d76a6817fb0ebc5a3c5e4&scene=21#wechat_redirect

vim 中操作符和动作:
https://vimjc.com/vim-operator-and-motion.html

vim 键盘速查表
https://vimjc.com/vim-chinese-cheatsheet.html