跳到主要内容

搜索与替换

搜索与替换是文本编辑中最常用的功能之一。Vim 提供了强大的搜索和替换功能,支持正则表达式,能够高效处理大量文本。

搜索

基础搜索

命令作用
/{pattern}向前搜索
?{pattern}向后搜索
n跳到下一个匹配
N跳到上一个匹配

示例

/function    " 向前搜索 function
?variable " 向后搜索 variable
n " 下一个匹配
N " 上一个匹配

搜索当前单词

命令作用
*向前搜索光标下的完整单词
#向后搜索光标下的完整单词
g*向前搜索光标下的部分匹配
g#向后搜索光标下的部分匹配

区别

  • * 只匹配完整单词(如搜索 the 不会匹配 then
  • g* 匹配部分(如搜索 the 也会匹配 then

搜索选项

设置搜索行为:

:set hlsearch      " 高亮所有匹配
:set nohlsearch " 关闭高亮
:set incsearch " 增量搜索(输入时实时显示)
:set ignorecase " 忽略大小写
:set smartcase " 智能大小写(有大写字母时区分大小写)
:set wrapscan " 循环搜索(到文件末尾后从头开始)

临时关闭高亮

:noh 或 :nohlsearch    " 临时关闭高亮,下次搜索重新开启

特殊字符搜索

搜索特殊字符需要转义:

/\.       " 搜索点号
/\* " 搜索星号
/\$ " 搜索美元符号
/\\ " 搜索反斜杠
/\/ " 搜索斜杠

正则表达式搜索

Vim 支持强大的正则表达式:

/^hello       " 搜索行首的 hello
/world$ " 搜索行尾的 world
/^$ " 搜索空行
/\<word\> " 搜索完整单词 word
/f[aei]st " 搜索 fast, fest, fist
/a\.\+b " 搜索 a 和 b 之间有任意字符

替换

基础替换命令

替换命令格式:

:[范围]s/旧文本/新文本/[标志]

示例

:s/old/new/           " 替换当前行第一个匹配
:s/old/new/g " 替换当前行所有匹配
:%s/old/new/g " 替换整个文件所有匹配
:5,10s/old/new/g " 替换第 5-10 行

范围指定

范围含义
当前行
%整个文件
n第 n 行
n,m第 n 到 m 行
.当前行
$最后一行
n,$第 n 行到末尾
'+a标记 a 所在行
'+a,'+b标记 a 到标记 b

示例

:1,50s/foo/bar/g      " 替换 1-50 行
:.,$s/foo/bar/g " 从当前行到末尾
:'a,'bs/foo/bar/g " 从标记 a 到标记 b

替换标志

标志含义
g全局替换(每行所有匹配)
c每次替换前确认
i忽略大小写
I区分大小写
n只计数,不实际替换
e无匹配时不显示错误

确认替换时的选项

y - 替换当前匹配
n - 跳过当前匹配
a - 替换所有剩余匹配
q - 退出替换
l - 替换并退出
Ctrl+e - 向上滚动
Ctrl+y - 向下滚动

实用替换示例

删除行尾空格

:%s/\s\+$//g

删除空行

:%s/^\n//g          " 删除空行(简单版)
:g/^$/d " 删除空行(更好)

替换 Tab 为空格

:%s/\t/    /g       " 一个 Tab 换 4 个空格

在行首添加注释

:5,20s/^/# /g       " 5-20 行添加 # 注释

删除行首数字

:%s/^\d\+\.\s*//g

全局命令

全局命令 g 对所有匹配行执行操作:

:[范围]g/模式/命令

示例

:g/foo/d              " 删除所有包含 foo 的行
:g!/foo/d " 删除所有不包含 foo 的行
:g/^$/d " 删除所有空行
:g/^#/y a " 复制所有以 # 开头的行到寄存器 a
:g/pattern/t$ " 复制所有匹配行到文件末尾

搜索与替换技巧

使用上次搜索模式

//           " 使用上次搜索模式向前搜索
?? " 使用上次搜索模式向后搜索
:%s//new/g " 使用上次搜索模式进行替换

使用上次替换模式

:~           " 使用上次替换的搜索模式
:& " 重复上次替换
:&g " 重复上次替换,添加 g 标志

替换中的特殊符号

:%s/old/\r/g          " \r 表示换行
:%s/old/\n/g " \n 表示空字符(在替换中)
:%s/old/&more/g " & 表示匹配的内容
:%s/\(.*\)/\1 copy/g " \1 表示第一个捕获组

可视化模式替换

在可视模式中选中区域后,按 : 会自动填充范围:

1. 选中要替换的区域(可视模式)
2. 按 :
3. 自动显示 :'<,'>(表示选中区域)
4. 输入 s/old/new/g

多文件搜索替换

使用参数列表

:args *.txt           " 将所有 txt 文件加入参数列表
:argdo %s/old/new/gce " 在所有参数文件中进行替换
:argdo update " 保存所有修改的文件

使用缓冲区列表

:bufdo %s/old/new/gce " 在所有缓冲区中替换

使用窗口列表

:windo %s/old/new/gce " 在所有窗口中替换

搜索历史

查看和重用搜索历史

q/          " 打开搜索历史窗口(向前搜索)
q? " 打开搜索历史窗口(向后搜索)

在搜索历史窗口中:

  • Enter 执行选中的搜索
  • 可以编辑历史记录后执行

命令行历史

q:          " 打开命令历史窗口

实战案例

案例 1:批量修改变量名

:%s/\<oldName\>/newName/g

使用 \<\> 确保只替换完整单词。

案例 2:格式化列表

原始文本:
apple
banana
cherry

目标:变成 "apple", "banana", "cherry"

:%s/^/"/g " 行首添加双引号
:%s/$/"/g " 行尾添加双引号
:%s/\n/, /g " 换行符替换为逗号空格

案例 3:函数名重构

# 将 getUserName 改为 get_user_name
:%s/getUserName/get_user_name/g

# 更通用的驼峰转下划线(需要更复杂的正则)
:%s/\([a-z]\)\([A-Z]\)/\1_\L\2/g

案例 4:提取特定行

:g/console\.log/y A        " 复制所有 console.log 到寄存器 A
:enew " 新建文件
"ap " 粘贴寄存器 a 的内容

案例 5:批量添加行号

:%s/^/\=line('.').'. '/g

结果:

1. 第一行
2. 第二行
3. 第三行

练习

练习 1:基础搜索

1. 打开任意代码文件
2. 用 / 搜索函数名
3. 用 n/N 浏览所有匹配
4. 用 * 搜索当前单词
5. 尝试 :set hlsearch 和 :set nohlsearch

练习 2:基础替换

1. 创建一个测试文件
2. 练习 :s/old/new/
3. 练习 :s/old/new/g
4. 练习 :%s/old/new/g
5. 练习带确认标志的替换 :%s/old/new/gc

练习 3:正则表达式

1. 搜索行首的单词:/^\w\+
2. 搜索行尾的标点:/[.!?]$/
3. 搜索空行:/^$/
4. 搜索包含数字的行:/\d\+

练习 4:实用替换

1. 删除文件中所有行尾空格
2. 删除所有空行
3. 将所有 Tab 替换为 4 个空格
4. 给所有行添加行号前缀

搜索替换总结

操作命令
向前搜索/pattern
向后搜索?pattern
下一个匹配n
上一个匹配N
当前行替换:s/old/new/g
全局替换:%s/old/new/g
确认替换:%s/old/new/gc
删除匹配行:g/pattern/d
复制匹配行:g/pattern/t$

下一步

搜索替换是 Vim 的强大功能,配合正则表达式可以处理复杂的文本操作。下一章我们将学习可视模式,这是进行选择性编辑的重要工具。