9.1 vi 与 vim

9.1.1 为何要学 vim

四大理由按重要性排序:

  1. 太多 Linux 指令默认调用 vi(crontab -e, visudo, edquota 等)——不学根本没法用
  2. 所有 Unix Like 系统都内置 vi,nano 不一定有
  3. vim 有语法高亮+程序编辑能力,通过颜色辅助除错
  4. 纯键盘操作,编辑速度极快

vi 是老式文本编辑器;vim = Vi IMproved。vim 支持语法高亮、正则搜索、多文件编辑、区块复制。vim 官网自称”程序开发工具”——鸟哥整个网站都是用 vim 写的。CentOS 7 中 vi 已被 alias 为 vim

9.2 vi 的使用

vi 共三种模式,编辑模式与命令行模式不能直接切换,必须通过一般指令模式中转

一般指令模式(command mode) ←→ 编辑模式(insert mode)
        ↕
命令行模式(command-line mode)

9.2.1 简易执行范例

/bin/vi welcome.txt     # 一般帐号要打绝对路径(因为 alias vi=vim)
  1. 进入一般指令模式 → 按 i → 进入编辑模式(左下角出现 —INSERT—)
  2. 打字 → 按 Esc → 回到一般指令模式
  3. :wq → 存盘离开(write + quit)
  4. 权限不够时 :wq! 强制写入;:q! 不存盘离开

9.2.2 按键说明

第一部份:一般指令模式

移动光标:

功能
h/j/k/l左/下/上/右(右手四指标准指法)
Ctrl+f/Ctrl+b下翻页/上翻页(= PageDown/PageUp)
Ctrl+d/Ctrl+u下半页/上半页
0/Home行首;$/End = 行尾
gg文件第一行;G = 最后一行
20G跳到第 20 行
H/M/L屏幕最上方/中央/最下方

搜索与替换:

功能
/word向下搜索;?word = 向上搜索
n重复上次搜索(同方向);N = 反向
:n1,n2s/old/new/g第 n1~n2 行间替换
:1,$s/old/new/gc全文替换+逐个确认(最安全!)

删除、复制、粘贴:

功能
x/X向后/向前删一个字符
dd删整行;20dd = 删 20 行
d1G/dG/d$/d0删到第一行/最后一行/行尾/行首
yy复制整行;20yy = 复制 20 行
y1G/yG/y0/y$复制到第一行/最后一行/行首/行尾
p/P贴在下一行/上一行
J合并下一行到当前行尾
u撤销;Ctrl+r = 重做
.重复上一个动作(神键!)

数字在 vi 中是幂等操作:5dd = 删 5 行;3yy = 复制 3 行;4j = 下移 4 行。

第二部份:进入编辑模式(记 i, o, R 就够):

功能
i光标处插入(最常用);I = 行首插入
a光标下一字符;A = 行尾插入
o下一行新增一行并插入O = 上一行新增
r替换一个字符;R = 连续替换(—REPLACE—)

第三部份:命令行模式

功能
:w存盘;:w! = 强制存盘
:q离开;:q! = 不存盘离开
:wq存盘离开(= ZZ,有修改才存)
:w filename另存新文件
:r filename读入另一个文件到光标后
:n1,n2 w filename第 n1~n2 行另存
:! command临时执行一次命令(如 :! ls /home
:set nu/:set nonu显示/隐藏行号

9.2.3 一个案例练习

练习文件:cp /etc/man_db.conf /tmp/vitest/,用 vi 完成以下操作验证熟练度:

  1. :set nu 显示行号 → 43G59→ 跳转到第 43 行第 59 字符
  2. gg/gzip 搜索
  3. :29,41s/man/MAN/gc 替换并逐个确认
  4. 66G6yyGp 复制 6 行贴到文末
  5. 113G16dd 删 16 行
  6. :w man.test.config 另存
  7. 25G15x 删 15 字符
  8. 1GO 在第一行上方新增一行

9.2.4 vim 的暂存盘、救援回复与打开时的警告讯息

vim 编辑时自动创建 .filename.swp 暂存盘。不正常退出后 swp 残留,再次打开会出现六个选项:

选项含义使用场景
[O]pen Read-Only只读打开只想看,不改
[E]dit anyway正常编辑危险!可能导致多人编辑冲突
[R]ecover从暂存盘恢复找回未保存的修改
[D]elete it删除暂存盘确认没用了(最常用)
[Q]uit / [A]bort放弃离开

9.3 vim 的额外功能

9.3.1 区块选择(Visual Block)

功能
v字符选择;V = 行选择
Ctrl+v矩形区块选择(列编辑神器!)
y复制反白区块;d = 删除;p = 贴上

9.3.2 多文件编辑

vim file1 file2    # 同时打开多个文件
:files             # 查看所有打开文件列表
:n                 # 下一个文件;:N = 上一个文件

跨文件复制:file1 里 yy:n 切到 file2 → p 粘贴。

9.3.3 多窗口功能

:sp                # 同一文件水平分屏
:sp filename       # 新窗口打开另一个文件
Ctrl+w+↓           # 光标移到下方窗口
Ctrl+w+↑           # 光标移到上方窗口
Ctrl+w+q           # 关闭当前窗口

9.3.4 vim 的挑字补全功能

组合键补全内容
Ctrl+x → Ctrl+n当前文件中出现过的词
Ctrl+x → Ctrl+f当前目录下的文件名
Ctrl+x → Ctrl+o按扩展名的语法内置关键字(需正确扩展名)

9.3.5 vim 环境设置与记录: ~/.vimrc, ~/.viminfo

不要改 /etc/vimrc,在自家目录创建 ~/.vimrc

" 双引号开头是注解
set hlsearch        " 高亮度反白搜索结果
set backspace=2     " 退格键可删任意字符
set autoindent      " 自动缩排
set ruler           " 右下角显示行列号
set showmode        " 左下角显示 --INSERT--/--REPLACE--
set nu              " 显示行号
set bg=dark         " 深色背景(注释深蓝色不刺眼)
syntax on           " 语法高亮

vim 自动记录上次搜索词和光标位置到 ~/.viminfo——下次打开同一文件光标还在原位置。

9.3.6 vim 常用指令示意图

参考原书图 9.3.10,汇总了各模式下常用按键。按 :set all 查看所有设置;按 :set 只看已修改的设置。

9.4 其他 vim 使用注意事项

9.4.1 中文编码的问题

中文乱码 = 文件编码与终端编码不一致。要正确显示:

  1. 确认 Linux 系统默认语系(/etc/locale.conf
  2. 确认终端 bash 的语系(LANG, LC_ALL
  3. 确认文件原本的编码(big5 还是 utf8)
  4. 在 GNOME 终端 → “终端机” → “设置字符编码” → 选对应编码
LANG=zh_TW.big5; export LC_ALL=zh_TW.big5    # 临时切为 big5

9.4.2 DOS 与 Linux 的断行字符

DOS/Windows 换行:CRLF^M$),Linux:LF$)。多了 ^M 会导致 shell script 无法执行。

dos2unix [-kn] file [newfile]    # CRLF → LF
unix2dos [-kn] file [newfile]    # LF → CRLF
# -k: 保留原 mtime;-n: 保留旧文件,输出到新文件
 
dos2unix -k -n old.txt new.txt   # 转换+保留原文件

9.4.3 语系编码转换

iconv -f 原编码 -t 新编码 filename [-o newfile]
iconv --list                     # 查看支持的编码
 
iconv -f big5 -t utf8 old.txt -o new.txt     # Big5 → UTF-8
# 正体 utf8 → 简体 utf8:需要两次中转(utf8→big5→gb2312→utf8)

关键命令

必须背的i, Esc, :wq, :q!, dd, yy, p, u, /word, n, gg, G, o, R, ., :set nu

记住就够用的Ctrl+v 矩形块、:sp 分屏、:1,$s/old/new/gc 替换、:! cmd 临时执行

遇到再查的:set all、vimrc 写法、Ctrl+x 补全系列