Linux上最常用的文本编辑器是vim
,但老实说也很难学,光一个编辑器使用指南就可以写一篇文章,在现在这个软件越来越易用的年代也算是另类了。
尤其是我们还有很多替代方式,比如nano
,或者干脆使用图形化的编辑器,比如VSCode的Linux版本,甚至还可以用Windows上的IDE远程连接后进行编辑(以前工作的时候我就是用Zend远程连接修改和debug测试机上的程序的),这都很方便,而且还是你熟悉的工具。
但是vim
依然有其存在的价值,比如说因为是命令行程序,可以在各种ssh
连接工具上直接调用,而且不依赖于XWindow
桌面,像一些出于安全或者性能方面考虑而不安装XWindow
的Linux主机,除了用IDE远程连接外就只能使用nano
或者vim
这样的工具了。
而vim
的功能显然要远远超过nano
。
下面介绍vim
的使用方式。
vi
与vim
vim
是在vi
的基础上开发的,比vi
更强大,可以看作是vi
的增强版,具体来说,主要是增加了编程相关的支持,对于不同的程序语言提供相应的语义颜色显式的支持,这点对开发者非常重要,对于运维来说,同样支持shell脚本的颜色显式。
[icexmoon@xyz ~]$ whereis vi vim
vi: /usr/bin/vi /usr/share/man/man1/vi.1.gz /usr/share/man/man1p/vi.1p.gz
vim: /usr/bin/vim /usr/share/vim /usr/share/man/man1/vim.1.gz
[icexmoon@xyz ~]$ alias vi
alias vi='vim'
虽然CentOS7上同时安装了vi
和vim
,但是可以看到存在一个命令别名vi
,实质上是调用vim
,也就是说默认情况下在bash中执行vi
都是使用的vim
,如果要调用真正的vi
,需要这样:
[icexmoon@xyz tmp]$ \vi test.py
[icexmoon@xyz tmp]$ /bin/vi test.py
使用vi
打开一个测试用的python
代码,效果是这样的:
使用vim
打开,效果这样:
区别还是很明显的。
vim
除了上边说明的vim
存在的意义以外,vim
还是很多shell程序调用的默认编辑器,也就是说如果某些应用执行的时候需要编辑一个文本文件,就会直接调用vim
来打开该文件,然后让用户编辑,这种情况下你就必须会用vim
了,也无法用其它方式去替代。
vi
的使用这里先介绍vi
的用法,最后再介绍vim
增强的功能,因为它们都是一脉相承,除了增强的功能以外用法都是一样的。
vi
最难令初学者理解的地方在于,作为一个文本编辑器,居然还分为三种工作模式,而且一开始打开后并非处于文本编辑模式,你不能随意移动光标编辑文本,这就很让人费解了,我第一次打开的时候完全是莫名其妙。
具体来说是分为以下三种模式:
指令模式(command mode):
指令模式也是一开始进入程序后的默认模式,在这个模式下可以直接使用各种快捷键对文本进行直接修改,也可以输入一些特殊字符进入命令模式。
输入模式(insert mode):
在指令模式下输入特殊字符(比如i
),后可以进入输入模式,或者叫做编辑模式。
在这个模式下我们可以像使用普通的文本编辑器那样移动光标,进行删除,或者输入文字。按ESC
可以退出到指令模式。
命令行模式(command-line mode):
在指令模式下输入/
、?
或:
可以进入命令行模式,前两个符号用于检索,最后一个用于输入命令。
在命令行下可以输入字符串进行检索,或者是使用各种命令实现各种功能,比如修改vi
的相关设置,或者对修改内容进行写入,亦或者退出应用。
按ESC
可以返回到指令模式。
三种模式的转换可以用下图表示:
(图片来自鸟哥的私房菜)
使用vi filename
可以打开一个文件,如果文件不存在,会新建,比如:
可以看到,左下角是文件名,以及[New File]
,表示这是一个新文件。
这是一个已经存在的文件,可以看到左下角的信息,表示文件是test.py
,只有1行数据,包含23个字符。
在指令模式下按下i
就可以进入输入模式:
此时左下角会出现为INSERT
字样,并且可以在该模式下移动光标并输入字符。
这个简单,在输入模式下按ESC
即可返回指令模式。
输入:
即可进入命令行模式:
此时光标会出现在左下方的:
字符之后,然后你就可以在这里输入相关命令并且按下Enter
执行,这里我们输入wq
以保存修改并退出。
使用cat
查看修改结果:
[icexmoon@xyz tmp]$ cat test.py
print("hellow wolrd!")
print("end")
这里wq
是最长用的保存并退出,如果不想保存,想直接退出,可以q
,但如果内容有变更,是不允许你这样离开的,需要使用q!
强制退出。如果文件没有写权限,同样是无法执行w
命令的,此时如果你是该文件的拥有者或者root
用户,可以使用w!
强制写入。类似的wq!
是强制写入后退出。
以上就是最简单的vi
操作流程,当然vi
的功能远远不止如此,这在后边详细说明。
这里将vi
中可以使用的按键和命令按模式划分为三部分:
为了更好地进行
vim
相关测试,这里下载了我的一个项目以提供文本文件,不过需要先安装工具git
:sudo yum install git
,如果无法安装的可能还需要替换CentOS
的源为国内的源:CentOS配置本地yum源/阿里云yum源/163yuan源,并配置yum源的优先级,当然这并不是必须的,你可以上传自己喜欢的文本到虚拟机中进行测试。
- 下边按键中的
d
>n>G
之类的表示依次输入某个按键,比如这个就表示先输入d
,再输入一个数字,最后再输入G
。- 下边按键中的未被代码模块包裹的n字母表示输入任意一个数字,比如20。
+
表示组合键。
按键 | 作用 |
---|---|
h 或方向键左 |
向左移动光标 |
j 或方向键下 |
向下移动光标 |
k 或方向键上 |
向上移动光标 |
l 或方向键右 |
向右移动光标 |
n>l 或n>方向键右 |
向右移动n个字符的光标 |
Ctrl+f 或PageDown |
向下翻页 |
Ctrl+b 或PageUp |
向上翻页 |
Ctrl+d |
向下移动半页 |
Ctrl+u |
向上移动半页 |
+ |
移动到非空白字符的下一行行首 |
- |
移动到非空白字符的当前行首 |
n>空格 |
移动到n个字符之后 |
0 或Home |
移动到行首 |
$ 或End |
移动到行尾 |
H |
移动光标到当前页第一行(非空)的行首 |
M |
移动光标到当前页中间行(非空)的行首 |
L |
移动光标到当前页最后一行(非空)的行首 |
G |
移动光标到最后一行 |
n>G |
移动光标到第n 行 |
g >g |
移动光标到首行,相当于1G |
x 或delete |
删除当前光标之后的一个字符 |
X |
删除当前光标之前的一个字符 |
n>x |
向后删除n个字符 |
dd |
删除光标所在的一整行 |
n>dd |
删除光标以下的n行 |
d >n>G |
删除光标所在行到第n行的所有行 |
d >g >g |
删除光标所在行到第一行的所有行,相当于d1G |
d >G |
删除光标所在行到最后一行 |
d >$ |
删除光标到行尾的字符,不包含光标所在字符 |
d >0 |
删除光标到行首的字符,不包含光标所在字符 |
y >y |
复制光标所在行 |
n>y >y |
向下复制n行 |
y >n>G |
复制到第n行之间的所有行 |
y >g >g |
复制到首行的所有行,相当于y1G |
y >G |
复制到最后一行之间的所有行 |
y >0 |
复制到行首的字符 |
y >$ |
复制到行尾的字符 |
p |
粘贴到光标的下一行 |
P |
粘贴到光标的上一行 |
J |
合并当前行和下一行 |
u |
撤销上一个操作 |
Ctrl +r |
恢复上一个操作 |
. |
重复上一个操作 |
在我实际尝试后,有这么几个感受:
hjkl
这几个键都在一排,但并不像wsad
那样结构和方向键一样,反而让人摸不着头脑,还是推荐使用方向键。PageDown
和PageUp
更为直观,而且Ctrl+f
在某些ssh
连接终端本身就被赋予了其它操作,比如查找。在指令模式中输入以下按键可以进入输入模式:
按键 | 作用 |
---|---|
i 或I |
进入输入模式,且光标停留在当前位置 |
a 或A |
进入输入模式,且光标停留在下一个字符 |
o 或O |
进入输入模式,在下一行插入一个空行,且光标停留在行首 |
r |
进入输入模式,在输入一个字符后会替换掉光标之后的字符,并退出 |
R |
进入输入模式,输入的字符会替换掉光标之后的字符 |
ESC |
从输入模式退出到指令模式 |
命令 | 用途 |
---|---|
:w |
将变更的数据写入文件 |
:w! |
强行写入文件(常用于没有写入权限时) |
:q |
退出vi |
:q! |
强行退出(常用于有变更数据,但是不想保存) |
:wq |
写入变更数据后退出 |
:wq! |
强行写入变更数据后退出 |
ZZ |
若文件没有修改,则不报错退出,若文件有修改,则保存后退出 |
:w [filename] |
将编辑中的内容写入另一个文件(相当于另存为) |
:r [filename] |
读取指定文件,并将内容插入下一行 |
:n1,n2 w [filename] |
将n1~n2行的数据写入指定文件 |
! [command] |
执行shell命令,执行完后按Enter 返回vi 界面 |
:set [vi_set] |
设置一些vi 的参数,比如:set nu 可以显示行号(仅对当前有效) |
/[words] |
向下查找输入的字符串 |
?[words] |
向上查找输入的字符串 |
n |
下一个查找结果 |
N |
方向查找 |
:n1,n2s/[words1]/[words2]/g |
将第n1行到第n2行的[words1] 替换为[words2] |
:1,$/[words1]/[words2]/g |
将全文中的[words1] 替换为[words2] |
:1,$/[words1]/[words2]/gc |
替换全文的[words1] 为[words2] ,并在替换是询问用户 |
练习案例可以使用鸟哥的私房菜的案例。
练习文本可以这样下载
[icexmoon@xyz vitest]$ wget http://linux.vbird.org/linux_basic/03
很多文字处理工具都有恢复之前的录入数据的功能,也就是说你还没来得及保存就遇到某些突发事件,比如电脑断电关机或者程序崩溃,在这些情况下依然可以找回还没来得及保存的数据。
我们的vi
也可以做到,打开任意文件,修改后不要保存,直接关闭ssh
连接,这样就相当于程序非正常终止。然后到文本文件所在的目录看一下:
[icexmoon@xyz vitest]$ ls -al
总用量 36
drwxrwxr-x. 2 icexmoon icexmoon 72 8月 13 17:22 .
drwxrwxrwt. 28 root root 4096 8月 13 17:23 ..
-rw-rw-r--. 1 icexmoon icexmoon 4850 8月 13 17:15 man_db.conf
-rw-r--r--. 1 icexmoon icexmoon 16384 8月 13 17:22 .man_db.conf.swp
-rw-rw-r--. 1 icexmoon icexmoon 4847 8月 13 17:14 man_test.config
出现了一个.man_db.conf.swp
的文件,这个文件就是vi
产生的临时文件,用于记录你编辑的还没有保存的信息,自然可以利用这个文件进行恢复。
现在重新用vi
打开文件:
E325: ATTENTION
Found a swap file by the name ".man_db.conf.swp"
owned by: icexmoon dated: Fri Aug 13 17:22:53 2021
file name: /tmp/vitest/man_db.conf
modified: YES
user name: icexmoon host name: xyz.icexmoon.centos
process ID: 5573
While opening file "man_db.conf"
dated: Fri Aug 13 17:15:56 2021
(1) Another program may be editing the same file. If this is the case,
be careful not to end up with two different instances of the same
file when making changes. Quit, or continue with caution.
(2) An edit session for this file crashed.
If this is the case, use ":recover" or "vim -r man_db.conf"
to recover the changes (see ":help recovery").
If you did this already, delete the swap file ".man_db.conf.swp"
to avoid this message.
"man_db.conf" 122L, 4850C
Press ENTER or type command to continue
这里提醒我们文件没有正常退出,并且可以使用:recover
命令进行恢复。
按Enter
打开文件后,进行恢复,然后保存退出:
[icexmoon@xyz vitest]$ ls -al
总用量 36
drwxrwxr-x. 2 icexmoon icexmoon 72 8月 13 17:30 .
drwxrwxrwt. 28 root root 4096 8月 13 17:28 ..
-rw-rw-r--. 1 icexmoon icexmoon 4832 8月 13 17:30 man_db.conf
-rw-r--r--. 1 icexmoon icexmoon 16384 8月 13 17:22 .man_db.conf.swp
-rw-rw-r--. 1 icexmoon icexmoon 4847 8月 13 17:14 man_test.config
[icexmoon@xyz vitest]$ cat man_db.conf | head -n 10
#
#
# This file is used by the man-db package to configure the man and cat paths.
# It is also used to provide a manpath for those without one by examining
# their PATH environment variable. For details see the manpath(5) man page.
#
# Lines beginning with `#' are comments and are ignored. Any combination of
# tabs or spaces may be used as `whitespace' separators.
#
# There are three mappings allowed in this file:
文件内容是对了,但是swp
文件依然存在,且再次进入后还是会有提示信息,这时候只能手动删除了:
[icexmoon@xyz vitest]$ rm .man_db.conf.swp
vi
和vim
的恢复方式和提示信息有所不同,vim
有更多的恢复选项:交换文件 ".man_db.conf.swp" 已存在! 以只读方式打开([O]), 直接编辑((E)), 恢复((R)), 删除交换文件((D)), 退出((Q)), 中止((A)):
这几个选项的用途是:
[O]
(open read-only):用只读方式打开文件,不进行任何编辑操作[E]
(edit anyway):直接载如当前的文件内容,不理会swp
中的未写入的修改内容[R]
(recover):使用swp
中缓存的修改内容进行恢复,同样需要在保存后手动删除swp
文件[D]
(delete it):确定swp
缓存文件没用,直接删除该文件[Q]
(quit):退出[A]
(abort):忽略并退出,相当于[Q]
前边说了,vim
可以看作是vi
的增强版:
用vim
打开一个系统配置文件/etc/services
,可以看到不仅使用紫色标识注释内容,而且右下角542,18
还显示当前光标处于542
行18
列,4%
是当前页面的进度占整个文件的长度是4%。
vim
还支持区块选择,这里我们先下载一个用于练习的文本:
[icexmoon@xyz vitest]$ wget http://linux.vbird.org/linux_basic/0310vi/hosts
按下v
之后移动光标,光标经过的内容都将被选定:
按ESC
或再次按v
可以取消选定。
按V
后移动光标可以选定整行:
按下Ctrl+v
后移动光标可以选定一个矩形区域:
之后的操作就和命令模式下对单个字符的操作相同了:
y
复制d
删除p
粘贴这个功能应该用于复制粘贴代码挺有用的,比需要按行号计算需要复制几行,然后nyy
这样的操作要直观许多。
有时候我们在编写代码的时候需要在多个文件之间复制粘贴,也就是多文件编辑,vim
同样支持。
使用vim
同时打开两个文件:
[icexmoon@xyz note5]$ vim test_v1.py test2_v1.py
在vim
中输入:files
命令:
可以看到当前打开了两个文件,且当前显示的是test_v1.py
这个文件。
按下V
后选择需要复制的代码:
按y
复制,然后输入:n
切换到另一个文件:
光标移动到最后一行后按p
粘贴:
然后输入:wq
保存离开。
关于多文件编辑的命令也很简单:
:files
:列出当前打开的所有文件:n
:切换到下一个文件:N
:切换到上一个文件:e [filename]
:打开一个新的文件,并切换到该文件有时候我们在写代码的时候需要参考另一个文件,或者是本文件的另一个部分,这时候我们都会将IDE窗口进行拆分,拆分成2个或者更多窗口,可以很方便的一边看另一个地方的代码一边编写当前的代码。
vim
同样支持这个功能!
这里打开一个84行的代码,并输入:sp
命令:
可以看到窗口切分成了2个,且都是显示同一个文件。
现在在上边的窗口中移动到需要复制的代码行,然后选中复制。
按下Ctrl+w
,然后再按下↓
:
此时光标移动到了下边的窗口,然后就可以在需要的地方粘贴复制的代码,或者是参考上边的窗格内容编写代码。
需要注意的是,在
Windows
中Ctrl+w
往往是关闭当前窗口的组合键,在Windows Terminal
中同样是关闭当前标签页的组合键,如果想屏蔽掉这个快捷键,需要修改WT的相关设置。
在多窗口模式下,要关闭哪个窗口只需要切换到该窗格后使用:q
退出即可,不会影响其它窗口。
多窗口功能有以下命令:
:sp [filename]
:打开指定文件,并用另一个窗口显示,如果没有指定文件,则将当前文件进行拆分显示。Ctrl+w
>↑
:切换到上边的窗口Ctrl+w
>↓
:切换到下边的窗口:q
:退出当前窗口在我们使用IDE编程的时候,往往只需要输入一个函数名的前几个字母,就能关联出完整的函数名,我喜欢将这个功能称作“智能联想”,而vim
也具有类似的功能。
具体有以下功能:
组合按钮 | 补全内容 |
---|---|
Ctrl+x >Ctrl+n |
依据当前文件的内容进行补全 |
Ctrl+x >Ctrl+o |
依据当前文件类型进行补全,(即根据文件扩展名类型) |
Ctrl+x >Ctrl+f |
依据当前文件的文件名进行补全 |
我本来想实际测试的,结果发现依据文件类型补全对
python
程序不起作用,而Ctrl+n
同样是WT的一个快捷键,好麻烦,就不打算继续折腾了,还是IDE好用…
vim
本身支持多种设置:
:set nu
:显示行号:set nonu
:不显示行号:set autoindent
:自动缩进:set noautoindent
:不自动缩进:set backup
:自动备份,开启后使用vim
编辑文件会自动生成一个filename~
的备份文件。:set ruler
:显示状态行(右下角那个行列信息):set showmode
:显示模式信息(左下角):set backspace
=(012):在输入模式下backspace
键是否可以删除字符,2
表示可以删除任意字符,0或1表示仅能删除新输入的字符。:set all
:显示全部设置:set
:显示用户修改过的设置:syntax on
:开启语法高亮:syntax off
:关闭语法高亮:set bg=dark
:背景为深色系:set bg=light
:背景为浅色系vim
的配置文件为/etc/vimrc
,但并不推荐直接修改这个文件,如果需要自定义配置,可以创建~/.vimrc
作为自己的vim
配置文件:
[icexmoon@xyz note2]$ vim ~/.vimrc
set nu "显示行`号
set autoindent "自动缩进
set ruler "显示状态行
set showmode "显示模式信息
set bg=dark "使用深色背景
syntax on "开启语法高亮
可以使用set nu
也可以使用:set no
,有没有:
不影响效果,注释可以使用"
。
修改好以后每次使用vim
都将使用这里的配置。
vim
中的常用指令可以参考下图:
(图片来资鸟哥的私房菜)
在使用Linux的时候难免会遇到各种中文乱码的问题,此时就需要排查各种编码和字符集的设置:
/etc/locale.conf
LANG
、LC_ALL
可以按照上边这个顺序进行排查。
[icexmoon@xyz note2]$ echo $LANG
zh_CN.UTF-8
[icexmoon@xyz note2]$ echo $LC_ALL
Linux
的换行符是\n
,而Windows
的换行符是\r\n
,所以以前如果要将Windows上编写的代码部署到Linux上就要处理换行符,否则会导致程序运行不正确。但现在已经没有此类问题了,IDE都会正确地自动处理换行问题。
当然,如果你的确遇到此类问题,可以尝试使用dos2unix
这个工具对代码进行转换。
如果没有安装此工具,可以使用yum install dos2unix
命令安装。
将Linux格式文件转换为Windows:
[icexmoon@xyz note2]$ cd /tmp
[icexmoon@xyz tmp]$ cp -a /etc/man_db.conf .
[icexmoon@xyz tmp]$ ll man_db.conf
-rw-r--r--. 1 icexmoon icexmoon 5171 10月 31 2018 man_db.conf
[icexmoon@xyz tmp]$ unix2dos -k man_db.conf
unix2dos: converting file man_db.conf to DOS format ...
[icexmoon@xyz tmp]$ cat -A man_db.conf
# ^M$
#^M$
# This file is used by the man-db package to configure the man and cat paths.^M$
# It is also used to provide a manpath for those without one by examining^M$
# their PATH environment variable. For details see the manpath(5) man page.^M$
#^M$
# Lines beginning with `#' are comments and are ignored. Any combination of^M$
# tabs or spaces may be used as `whitespace' separators.^M$
#^M$
# There are three mappings allowed in this file:^M$
# --------------------------------------------------------^M$
# MANDATORY_MANPATH^I^I^Imanpath_element^M$
上边转换成Windows格式的文件以^M$
为结尾,$
代表\n
,而^M
代表\r
。
转换回去:
[icexmoon@xyz tmp]$ dos2unix -k man_db.conf
dos2unix: converting file man_db.conf to Unix format ...
[icexmoon@xyz tmp]$ cat -A man_db.conf | head -n 10
# $
#$
# This file is used by the man-db package to configure the man and cat paths.$
# It is also used to provide a manpath for those without one by examining$
# their PATH environment variable. For details see the manpath(5) man page.$
#$
# Lines beginning with `#' are comments and are ignored. Any combination of$
# tabs or spaces may be used as `whitespace' separators.$
#$
# There are three mappings allowed in this file:$
如果某种编码的文件不能显示或使用,还可以使用icov
命令将其转换为可以使用的编码:
[icexmoon@xyz tmp]$ wget http://linux.vbird.org/linux_basic/0310vi/vi.big5
--2021-08-13 19:55:11-- http://linux.vbird.org/linux_basic/0310vi/vi.big5
正在解析主机 linux.vbird.org (linux.vbird.org)... 140.116.44.180
正在连接 linux.vbird.org (linux.vbird.org)|140.116.44.180|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:1498 (1.5K) [text/plain]
正在保存至: “vi.big5”
100%[===========================================================================================>] 1,498 --.-K/s 用时 0s
2021-08-13 19:55:23 (24.4 MB/s) - 已保存 “vi.big5” [1498/1498])
[icexmoon@xyz tmp]$ iconv -f big5 -t utf8 -o vi.utf8 vi.big5
打开vi.big5
显示乱码,但是vi.utf8
可以正常显示。
关于vim
相关的内容介绍完了,好像也表示很难?其实编辑器这东西,经常摸自然就熟练了。
谢谢阅读。