Appearance
Vim 搜索、替换与特殊用法
Vim 的搜索和替换不是简单的“查找字符串”。它和移动、文本对象、寄存器、命令行模式结合后,可以承担大量结构化编辑任务。
本文聚焦三个方向:
- 搜索和替换的日常用法。
- Vim 正则里容易混淆的特殊语法。
- 文本对象、屏幕移动、重复命令等高频特殊技巧。
搜索
基本搜索
vim
/pattern " 向后搜索
?pattern " 向前搜索
n " 沿相同方向找下一个
N " 沿相反方向找下一个
* " 向后搜索光标下单词
# " 向前搜索光标下单词
g* " 搜索包含光标下字符串的位置,不要求单词边界
g# " 反向 g*搜索后常配合跳转和修改:
vim
/TODO
n
ciwDONE<Esc>
n
.这表示:找到 TODO,改成 DONE,再到下一个匹配处重复修改。
搜索设置
vim
set ignorecase " 搜索忽略大小写
set smartcase " 搜索词包含大写时自动区分大小写
set incsearch " 输入搜索词时实时跳转
set hlsearch " 高亮搜索结果清除搜索高亮:
vim
:nohlsearch常用映射:
vim
nnoremap <leader><space> :nohlsearch<CR>搜索寄存器
最近一次搜索模式保存在 "/ 寄存器里。
vim
:echo @/
:let @/ = 'error'修改 @/ 后,按 n 会按新模式继续搜索。
替换
基本替换
vim
:s/old/new/ " 替换当前行第一个匹配
:s/old/new/g " 替换当前行所有匹配
:%s/old/new/g " 替换全文所有匹配
:%s/old/new/gc " 替换全文所有匹配,并逐个确认范围可以灵活指定:
vim
:10,20s/foo/bar/g " 第 10 到 20 行替换
:'<,'>s/foo/bar/g " 可视模式选区替换
:.,$s/foo/bar/g " 当前行到文件末尾替换确认替换
c 标志会逐个确认。
vim
:%s/foo/bar/gc确认时常用按键:
text
y 替换当前匹配
n 跳过当前匹配
a 替换当前和后续所有匹配
q 退出替换
l 替换当前匹配后退出使用上一次搜索作为替换目标
替换命令里省略搜索模式时,会使用上一次搜索。
vim
/foo
:%s//bar/g这适合先确认搜索结果,再执行替换。
替换中引用匹配
vim
:%s/\v(\w+)\s+(\w+)/\2, \1/g把两个词的顺序反过来。\1、\2 表示第 1、第 2 个捕获组。
不想捕获的分组可以用 \%():
vim
/\v%(And|D)rew Neil全局命令
:global 可以对匹配行执行命令。
vim
:g/TODO/p " 打印所有包含 TODO 的行
:g/TODO/d " 删除所有包含 TODO 的行
:v/TODO/d " 删除所有不包含 TODO 的行
:g/^$/d " 删除空行它也可以和普通命令结合:
vim
:g/TODO/normal! A # FIXME这表示对所有包含 TODO 的行,在行尾追加文本。
Vim 正则特殊语法
Vim 的正则和很多语言里的正则不完全一样。最重要的是 magic 模式和若干 Vim 专用标记。
magic、very magic、very nomagic
Vim 默认正则需要对部分特殊字符加反斜杠。为了让表达式更接近现代正则,可以使用 \v。
vim
/\vfoo|bar " very magic,| 具有特殊含义
/\Vfoo.bar " very nomagic,大多数字符按原义匹配实践建议:复杂搜索优先使用 \v,普通字符串搜索可直接输入。
常见字符类
vim
. " 任意字符,不含换行
\d " 数字
\D " 非数字
\w " 单词字符,包括字母、数字和下划线
\W " 非单词字符
\s " 空白字符
\S " 非空白字符
\x " 十六进制字符跨行匹配空白时使用 \_s:
vim
/\vfoo\_s+bar\_s 会匹配空白符或换行符。
单词边界
vim
/\<word\> " 精确匹配单词 word
/\v<word> " very magic 下的写法* 搜索光标下单词时,本质上也会使用类似单词边界的匹配。
控制匹配范围:\zs 与 \ze
\zs 标记匹配结果的开始,\ze 标记匹配结果的结束。它们常用于“上下文参与判断,但不进入最终匹配”。
vim
/\v"[^"]+" " 匹配包括引号在内的字符串
/\v"\zs[^"]+\ze" " 只匹配引号内部内容替换示例:
vim
:%s/\vclass="\zs[^"]+\ze"/active/g只替换 class="..." 里面的值,不替换引号和属性名。
分组与选择
vim
/\v(foo|bar) " 捕获分组
/\v%(foo|bar) " 非捕获分组替换时,捕获分组可以用 \1、\2 引用。
vim
:%s/\v(\w+),\s*(\w+)/\2 \1/g文本对象
文本对象让命令从“按字符移动”变成“按语义选择”。
常见格式:
text
操作符 + i/a + 对象i 表示 inner,不包含外侧符号或空白;a 表示 around,包含外侧符号或相关空白。
vim
ciw " 修改当前单词
daw " 删除当前单词及周围空白
yi" " 复制双引号内部
ca" " 修改整个双引号区域
di( " 删除括号内部
ya{ " 复制整个花括号区域
vip " 选中当前段落内部
dap " 删除当前段落常见对象:
vim
iw / aw " 单词
iW / aW " WORD,以空白分隔
i" / a" " 双引号
i' / a' " 单引号
i` / a` " 反引号
i( / a( " 圆括号
i[ / a[ " 方括号
i{ / a{ " 花括号
it / at " 标签
ip / ap " 段落
is / as " 句子文本对象是 Vim 从“移动光标”升级到“操作结构”的关键。
特殊移动与编辑习惯
屏幕内移动
vim
H " 移动到当前屏幕顶部
M " 移动到当前屏幕中间
L " 移动到当前屏幕底部
zz " 当前行居中
zt " 当前行置顶
zb " 当前行置底H、M、L 是按屏幕位置移动,不是按文件行号移动。
行内查找
vim
fx " 向后移动到字符 x
Fx " 向前移动到字符 x
tx " 向后移动到字符 x 之前
Tx " 向前移动到字符 x 之后
; " 重复上一次 f/t/F/T
, " 反向重复上一次 f/t/F/T示例:
vim
dt, " 删除到下一个逗号前
ct) " 修改到右括号前匹配跳转
vim
% " 跳到匹配的括号、注释边界或部分语言结构常见用法:
vim
d% " 删除到匹配位置
v% " 选中到匹配位置重复修改
vim
. " 重复上一次修改推荐把修改设计成单次动作:
vim
ciwnew<Esc>
n
.这样可以搜索下一个位置并重复同样修改。
可视块编辑
可视块适合列编辑。
vim
Ctrl-v " 进入块选择
I " 在块的每一行前插入
A " 在块的每一行后插入示例:给多行前面加 //:
vim
Ctrl-v
j j j
I// <Esc>推荐排查方式
遇到搜索或替换结果不符合预期时,可以这样排查:
- 先用
/pattern确认匹配范围,再用:%s//new/g替换。 - 复杂正则加
\v,减少反斜杠噪音。 - 需要保留上下文时,用
\zs和\ze控制真正替换的范围。 - 替换前先加
c标志逐个确认。 - 不确定命令含义时查
:help pattern、:help :substitute、:help text-objects。
