今日主题#
- 主主题:
搜索 / 替换 / 可视模式 - 副主题:
把“找到目标”接到“批量改”和“手动选中改”上
学习目标#
- 解决“知道怎么改,但找目标慢、批量改不稳、选区不顺手”的问题。
- 建立最常用的搜索路径:
/与?n与N*与#
- 建立最常用的替换路径:
:s:%sg与c标志
- 建立最常用的 Visual 选择路径:
vVCtrl-Vgv
前置回顾#
- Day 003 已经建立:
- operator 决定做什么
- motion 决定做到哪里
- Day 004 已经建立:
- 文本对象可以让范围更贴结构
- 但真实编辑里还有一个绕不过去的问题:
- 我得先更快找到目标
- 然后决定是单点改、批量改,还是选一块再改
- Day 005 的作用,就是把“找目标”和“改目标”接成一个完整闭环。
- 当前本地环境已确认:
Vim 9.2Neovim 0.12.0
典型场景#
这一篇要解决的是真实编辑里最常见的几类动作:
- 文件里同一个词出现很多次,想快速跳到下一个。
- 想把整篇里的某个词统一替换,但又不敢一次性全替。
- 想先手动选一块文本,再做删除、缩进或替换。
- 想在一个矩形区域里做列编辑。
如果前几天是在练“怎么改”,那今天是在练“怎么更稳地找到并改”。
最小命令集#
今天只保留最高频、最值得马上形成肌肉记忆的一层。
搜索#
/pattern- 向前搜索
?pattern- 向后搜索
n- 按当前搜索方向跳到下一个结果
N- 按相反方向跳到结果
*- 搜索光标下的单词,向前
#- 搜索光标下的单词,向后
替换#
:s/old/new/- 当前行替换一个匹配
:s/old/new/g- 当前行替换所有匹配
:%s/old/new/g- 全文件替换所有匹配
:%s/old/new/gc- 全文件替换所有匹配,并逐个确认
可视模式#
v- 字符级选择
V- 行级选择
Ctrl-V- 块选择
gv- 重新选中上一次 Visual 区域
- 在
Ctrl-V之后用I/A- 对多行做统一前缀插入或统一尾部追加
它是怎么用的#
核心心法:先找到目标,再决定是“跳着改”“批量改”还是“选中改”#
Day 005 最重要的不是命令量,而是决策顺序。
当你想改一段内容时,先问自己:
- 我是在找单个目标,还是重复目标?
- 我是想逐个看着改,还是整批改?
- 我是更适合搜索定位,还是更适合先选中再操作?
这三个判断,会自然导向:
- 搜索跳转
:substitute- Visual 选择
/、?、n、N:先把最基础的搜索循环练顺#
本地 pattern.txt 里把 / 和 ? 作为最基础的搜索命令:
/pattern- 向前找
?pattern- 向后找
而真正高频的,不只是发起搜索,而是搜索后的继续跳转:
n- 按当前搜索方向继续
N- 反方向继续
所以一个高频节奏通常是:
/targetnn- 看到需要处理的那个位置再动手
* 和 #:最适合“这个词我还会继续改”#
如果目标词已经在光标下,往往没必要再手打一遍搜索词。
本地帮助里对 * 和 # 的定义很直接:
*- 向前搜索光标下的词
#- 向后搜索光标下的词
这在改变量名、重复术语、配置键名时非常高频。
一个常见工作流是:
- 光标落在目标词上
*- 用
n/N在多个位置间跳 - 逐处用
ciw或别的动作修改
:s 和 :%s:先记住“当前行”和“全文件”#
替换最该先练顺的不是复杂正则,而是范围感。
今天先把这两个区别记牢:
:s/.../.../- 当前行
:%s/.../.../- 全文件
再加上两个最高频标志:
g- 一行内全部替换
c- 每次替换前确认
于是最常用的安全写法就是:
:%s/old/new/gc
它的价值在于:
- 范围够大
- 节奏够稳
- 不容易因为一次全替把文件改坏
c 标志:把批量改从“冒险”变成“受控”#
本地 change.txt 里对 :s 的 [c] 标志列出了交互选项:
y- 替换这一次
n- 跳过这一次
a- 这次以及后面全部替换
q或<Esc>- 退出替换
所以如果你对范围没有 100% 把握,优先用:
:%s/old/new/gc
它通常比一次性无脑全替更适合学习阶段。
Visual 模式:当“范围不好一句话说清”时,就先选出来#
本地 visual.txt 对 Visual mode 的定义非常直接:
- 先进入 Visual
- 再扩展选择
- 再对选区执行 operator
三种模式先只记用途,不要一开始背太多细节:
v- 适合字符级精细选择
V- 适合整行选择
Ctrl-V- 适合矩形块选择
这让你在以下场景里非常顺手:
- 这一小段我想删掉
- 这几行我想整体缩进
- 这一列我想一起改
gv:把“刚才那块区域”再拿回来#
gv 很值得早点记住,因为它能重新选中上一次 Visual 区域。
这对下面这种情况很有用:
- 你刚选了一块并做了操作
- 结果发现还想对同一块再做一个操作
例如:
V选几行>gvgq或别的操作
这会明显减少“重新选一次”的摩擦。
块选择最值钱的一招,不只是删,而是多行统一插入 I / A#
D:\program\Learn-Vim\ch11_visual_mode.md 里有一个很值得早学的动作:
- 先用
Ctrl-V选出一个矩形块 - 再用
I或A - 输入内容
- 最后按一次
<Esc>
这很适合下面这类场景:
- 多行前面统一补
# - 多行前面统一补
// - 多行末尾统一补
;
一个最小例子:
Ctrl-V jj I// <Esc>或者:
Ctrl-V jj$ A; <Esc>重点不是背命令,而是建立一个判断:
- 如果问题是“这一列都要改”
- 那就优先想到块选择,而不是把几行拆开逐条修改
常见操作套路#
套路 1:重复词逐个改,优先 * + n + 单点修改#
场景:
- 改同一个变量名的若干处
- 改文中的某个术语
更稳的方式:
- 光标放在目标词上
*n/N跳到下一个- 每次到位后再用
ciw、caw或别的动作修改
套路 2:整文件批量改,优先 :%s/.../.../gc#
场景:
- 全文统一术语
- 批量改配置项
- 批量改注释中的旧词
学习阶段的稳妥默认:
:%s/old/new/gc
先确认,再放行,比直接 g 全替更稳。
套路 3:范围说不清时,直接进 Visual#
场景:
- 这一小块我想删掉
- 这几行我想整体右移
- 这列前面我想统一补字符
如果你发现自己难以一句话说出范围,通常就别硬拼命令,直接:
vVCtrl-V
套路 4:块编辑只在确实是“列问题”时用 Ctrl-V#
Ctrl-V 很强,但不要乱用。
真正适合它的场景是:
- 多行相同列对齐
- 多行前面统一插入注释符号
- 多行末尾统一补内容
如果不是“矩形问题”,往往普通 Visual 或替换更自然。
环境差异:vim / nvim / LazyVim#
搜索、替换、Visual 都是 Vim / Neovim 的共同底层#
本地帮助里:
pattern.txt负责搜索change.txt负责替换visual.txt负责可视模式
这些都是 Vim 9.2 和 Neovim 0.12.0 共同保留的基础能力。
也就是说,今天学到的不是某个配置流派技巧,而是两边通用的底层编辑语法。
到了 LazyVim,这三者只会更常用#
LazyVim 会帮你更快找到文件和符号,但进入文件后,下面这些动作仍然大量出现:
/找目标*找重复词:%s/.../.../gc做受控批量改V或Ctrl-V先选区再操作
所以 Day 005 不是过渡章节,而是后面项目编辑和代码导航的直接前置能力。
今日练习(5-10 分钟)#
练习材料 A:基础搜索与替换#
新建一个临时文件,写入下面内容:
vim search should feel direct
search helps me find the next target
search can also help me replace repeated words
visual mode helps when the range is easier to see than to describe练习任务 A#
- 用
vim或nvim打开这个文件。 - 用
/search搜索search,然后用n和N在结果之间跳转。 - 把光标停在某个
search上,试一次*和#。 - 用
:s/search/find/在当前行替换一个匹配。 - 用
:%s/search/find/gc在全文件里逐个确认替换。 - 用
V选中两行,试一次删除或缩进。 - 用
Ctrl-V试着选一个矩形区域,感受它和普通 Visual 的区别。 - 用
gv重新选中刚才那块区域。
练习材料 B:术语批量修改#
再准备一个文件,写入:
server timeout happened once
server timeout happened twice
client timeout should be checked
server retry may hide a timeout练习任务 B#
- 先用
/timeout找到第一个timeout。 - 用
n/N在几个timeout之间来回跳。 - 光标停在
server上,试*,观察只找整词。 - 用
:%s/timeout/deadline/gc逐个确认替换。 - 只想改当前行时,再试一次:
:s/server/backend/g
练习材料 C:同一行多个条件#
再准备一个文件,写入:
error timeout user=alice
error retry user=bob
timeout only user=carol
error and timeout happened again练习任务 C#
- 试着搜索同时包含
error和timeout的行:/.*error\&.*timeout
- 用
n继续跳到下一个符合条件的行。 - 再试着只按整词搜索:
/.*\<error\>\&.*\<timeout\>
- 感受它和普通
/error、/timeout的差别。
练习材料 D:Visual 行选择#
再准备一个文件,写入:
alpha one
beta two
gamma three
delta four
epsilon five练习任务 D#
- 用
V选中中间两行。 - 对选区试一次:
><d
- 用
gv重新选回刚才的区域。 - 再用
y复制选区,找个空白处p粘贴。
练习材料 E:Visual 块选择#
再准备一个文件,写入:
item_apple price_12
item_banana price_08
item_orange price_15
item_grape price_11练习任务 E#
- 用
Ctrl-V选择apple、banana、orange、grape开头那一列的一部分。 - 观察块选择和普通
v/V的视觉差异。 - 对块选区试一次:
dcIA
- 撤销后重做一遍,试一次统一前缀:
Ctrl-V- 选中前几行左侧一列
I#<Esc>
- 如果操作后不满意,再撤销一次,只关注“这是矩形范围,不是连续文本范围”。
练习材料 F:缩进与重排#
再准备一个文件,写入:
if ready:
print("start")
if retry:
print("retry")
print("done")练习任务 F#
- 把第二到第五行用
V选起来。 - 试一次:
><
- 把光标放到某一行,试:
>><<
- 再试一次:
==- Visual 下
=
- 体会:
>/<更像机械左移右移=更像按规则重排
练习材料 G:综合闭环#
最后准备一个综合文件,写入:
user_name = "alice"
user_role = "guest"
user_state = "active"
admin_name = "bob"
admin_role = "guest"
admin_state = "active"练习任务 G#
- 用
/guest找到第一个guest。 - 用
n跳到第二个guest。 - 用
:%s/guest/member/gc逐个确认替换。 - 用
V选中admin_开头的三行,整体右移一次。 - 把光标落在某个
"active"上,试:*ci"
- 最后回顾这一个文件里你是否都用上了:
- 搜索
- 替换
- Visual
- 文本对象
完成标准#
- 能清楚区分
/、*、:s、:%s、v/V/Ctrl-V各自解决什么问题。 - 能说出为什么
:%s/old/new/gc比直接全替更稳。 - 能在至少一个场景里自然想到用 Visual,而不是硬拼复杂范围。
- 能从这些练习里分清三类场景:
- 找到目标再逐点修改
- 受控批量替换
- 先选区再操作
今日问题与讨论#
我的问题#
问题 1:什么时候该用 /pattern,什么时候该用 *?#
- 简答:
- 已经站在目标词上时优先
*;还没站上去时用/pattern。
- 已经站在目标词上时优先
- 场景:
- 改变量名时常从当前词出发;找任意目标文本时则通常先手打搜索。
- 依据:
- 本地
pattern.txt对*的定义就是搜索光标下单词,对/的定义是显式输入搜索模式。
- 本地
- 当前结论:
*是“就地继续找这个词”,/是“主动发起新搜索”。
- 是否需要后续回看:
否
问题 2:为什么学习阶段推荐 :%s/old/new/gc?#
- 简答:
- 因为它兼顾范围大和风险可控。
- 场景:
- 你想全文件统一替换,但又不确定每个匹配都该不该改。
- 依据:
- 本地
change.txt明确列出c标志的逐项确认行为。
- 本地
- 当前结论:
- 学习阶段优先用
gc,等你对范围更有把握,再考虑直接全替。
- 学习阶段优先用
- 是否需要后续回看:
是
问题 3:为什么已经有文本对象了,还需要 Visual 模式?#
- 简答:
- 因为不是所有范围都能被一句结构对象表达清楚。
- 场景:
- 某段跨多行但又不是完整结构对象的文本,或者一块矩形列区域。
- 依据:
- 本地
visual.txt把 Visual mode 定义成“选一块文本再交给 operator”,它解决的是显式选区问题。
- 本地
- 当前结论:
- 文本对象适合结构清晰的范围,Visual 适合“眼睛比语言更容易界定”的范围。
- 是否需要后续回看:
是
问题 4:Vim 搜索的 pattern 语法到底是什么?#
- 简答:
- 可以先把它理解成“普通字符 + 特殊原子 + 重复次数 + 分组/分支”四层结构。
- 场景:
- 你已经会
/pattern,但想进一步写出“词边界”“行首行尾”“可选项”“多个候选词”这类搜索。
- 你已经会
- 依据:
- 本地
pattern.txt把 pattern 拆成 branch、concat、piece、atom,并给出常用原子与 multi 项。
- 本地
- 当前结论:
- 学习阶段先掌握这组最常用骨架就够用:
- 普通字符:
foo - 分支:
foo\|bar - 重复:
*、\+、\=、\?、\{n,m} - 行首/行尾:
^、$ - 任意单字符:
. - 词边界:
\<word\>、\>、\< - 设置匹配起止:
\zs、\ze - 大小写控制:
\c、\C - magic 模式切换:
\v、\m、\M、\V - 搜索偏移:
/test/e、/test/s+2
- 是否需要后续回看:
是
问题 5:Vim 的缩进语法是什么?#
- 简答:
- 日常最常用的是三组:
>/<右移左移,=重新缩进,配合 motion、Visual 或整行双写。
- 日常最常用的是三组:
- 场景:
- 你想让一行右移、几行左移,或者让一段代码按当前缩进规则重新排整齐。
- 依据:
- 本地
change.txt里有shift-left-right和=operator,明确列出>>、<<、>{motion}、<{motion}、==、Visual 下的>/</=。
- 本地
- 当前结论:
- 高频记法先记这些:
>>/<<- 当前行向右 / 向左移动一个
shiftwidth
- 当前行向右 / 向左移动一个
>{motion}/<{motion}- 对一个 motion 覆盖到的范围右移 / 左移
V ... >/V ... <- 先行选区,再整体缩进
==- 重新缩进当前行
={motion}或 Visual 下=- 按当前语言缩进规则重排一段范围
- 缩进宽度主要由
shiftwidth决定 - 如果只是“机械右移/左移”,多想
>/< - 如果是“按语法重新排”,多想
=
- 是否需要后续回看:
是
问题 6:Visual 还有哪些简单但高频的操作?#
- 简答:
- 除了删和缩进,最常用的补充是复制、改、大小写切换、拼接行、换端点和重选。
- 场景:
- 你已经会
v / V / Ctrl-V进入选区,接下来想知道“选出来以后最常按什么”。
- 你已经会
- 依据:
- 本地
visual.txt说明 Visual 的核心就是“先选,再给 operator”;同时列出了gv、o、O等补充动作,很多普通 operator 也都能直接接在 Visual 后。
- 本地
- 当前结论:
- 最值得先记住的是:
d- 删除选区
c- 改选区,删掉后进入插入模式
y- 复制选区
>- 右移缩进
<- 左移缩进
=- 重新缩进
~- 切换选区大小写
u- 选区转小写
U- 选区转大写
J- 拼接选中的行
p- 用寄存器内容替换选区
o- 在 Visual 中跳到选区另一端
O- 在 blockwise Visual 中跳到另一角
gv- 重新选中上一次 Visual 区域
- 是否需要后续回看:
是
问题 7:Vim 搜索里能表达“同一行同时出现 A 和 B”吗?#
- 简答:
- 能。最直接的写法通常是用
\&,或者直接写成.*A\&.*B这种“同一位置同时满足两个条件”的模式。
- 能。最直接的写法通常是用
- 场景:
- 你在筛选日志、配置、文本行时,想找“这一行里既有 A 又有 B”的行,而不是只要出现其中一个就算。
- 依据:
- 本地
pattern.txt明确说明:branch 可以用\&连接,含义是几个 concat 必须在同一位置同时成立;文档还直接给了例子: .*Peter\&.*Bob- 匹配同时包含
Peter和Bob的一行
- 匹配同时包含
- 本地
- 当前结论:
- 最常用写法就是:
/.*A\&.*B- 匹配同一行同时包含 A 和 B
/.*error\&.*timeout- 匹配同时包含
error和timeout的行
- 匹配同时包含
- 顺序无关:
- 因为前面有
.*,A在前或B在前都能匹配
- 因为前面有
- 如果你想匹配整词,可以写:
/.*\<foo\>\&.*\<bar\>
- 如果你想进一步叠加第三个条件,也可以继续接:
/.*foo\&.*bar\&.*baz
- 是否需要后续回看:
是
外部高价值问题#
- 今日暂不引入外部问题。
- 原因:
- Day 005 先把本地可验证的高频查找和替换流程练顺。
常见误区或易混点#
- 误区 1:只会
/pattern就等于会搜索- 真正常用的是
/发起搜索后再用n/N持续跳转。
- 真正常用的是
- 误区 2:批量替换就应该直接
:%s/.../.../g- 学习阶段很多时候更该先用
gc。
- 学习阶段很多时候更该先用
- 误区 3:Visual 模式只是“鼠标选中”的键盘版本
- 不是。它和 operator、motion、块编辑都能形成自己的工作流。
- 误区 4:
Ctrl-V比普通 Visual 更高级,所以应优先使用- 不是。它只在矩形块场景里更合适。
- 误区 5:文本对象已经覆盖了 Visual 的作用
- 没有。两者解决的是不同类型的范围问题。
扩展内容#
g*/g#- 类似
*/#,但不要求整词匹配。
- 类似
\c/\C- 在搜索模式里临时控制大小写匹配。
:%s/old/new/g- 直接全替,等你对范围更有把握后再多用。
:s///- 复用上一轮替换模式,后面可以作为提速点。
\%V- 在替换里限制到 Visual 区域,后面可再补。
o/O- 在 Visual 里切换到选区另一端或块选择另一角,调整选区时很实用。
今日小结#
Day 005 最重要的是把三个动作连起来:
- 先找到
- 再判断范围
- 再决定是逐点改、批量改,还是选中改
一旦这条链顺起来,很多编辑任务就不再是“我会改,但改得很笨”,而会变成更稳定的闭环。
明日衔接#
下一步建议进入:
Day 006:buffer / window / split
重点会开始解决:
- 怎样在多个文件间切换
- 怎样同时看两处内容
- 怎样把“会编辑”推进到“会在多个上下文里编辑”
复习题#
/pattern、*、n、N分别最适合什么场景?:s和:%s的核心区别是什么?- 为什么学习阶段常优先推荐
:%s/old/new/gc? v、V、Ctrl-V分别更适合什么范围?- 文本对象和 Visual 模式分别更适合解决什么问题?


