跳过正文
  1. Posts/

Vim 学习笔记 Day 003:operator + motion,把“到位”变成“直接改掉”

·4180 字·9 分钟
📖 阅读 --
DogDu
作者
DogDu
工作结束或者累了, 要不休息一会, 看会动漫吧 ~
目录
Vim 14 天 - 这篇文章属于一个选集。
§ 3: 本文

今日主题
#

  • 主主题:operator + motion
  • 副主题:把移动真正接到删除、修改、复制上

学习目标
#

  • 解决“会移动了,但一改内容又退回插入模式乱修”的问题。
  • 明确 Vim 的很多编辑动作都不是独立命令,而是:
    • 先给一个 operator
    • 再给一个 motion
  • 建立最常用的组合直觉:
    • 删除一段范围
    • 修改一段范围
    • 复制一段范围
  • 为下一天的文本对象做准备。

前置回顾
#

  • Day 001 建立了模式心智模型:
    • 普通模式是主工作模式
    • 插入模式只是短暂停留
  • Day 002 建立了移动尺度:
    • h j k l 负责微调
    • w e b ge 0 ^ $ gg G 负责更直接的到位
  • 到了 Day 003,要把这两件事接起来:
    • 不是“先移动过去,再慢慢改”
    • 而是“直接对某个移动范围做操作”
  • 当前本地环境已确认:
    • Vim 9.2
    • Neovim 0.12.0

典型场景
#

这一篇要解决的是真实编辑里很常见的几种低效:

  • 想删掉当前词后面的内容,却先挪过去再反复退格。
  • 想把某个词改掉,却先进插入模式,再手动删,再重打。
  • 想复制到行尾或删到行首,却还在按字符处理。
  • 明明已经知道怎么移动,但还没有把移动变成“操作范围”。

如果你只学会移动,没有学会把移动当作编辑范围,Vim 的效率提升还只完成了一半。

最小命令集
#

今天只保留最常用、最能立刻带来手感变化的一组。

常用 operator
#

  • d
    • delete,删除
  • c
    • change,修改
  • y
    • yank,复制

最常用 motion
#

  • w / e / b
    • 按词定位
  • 0 / ^ / $
    • 行内定位
  • j / k
    • 跨行范围

最常用组合
#

  • dw
    • 删除到下一个词开头
  • de
    • 删除到当前词或下一个词结尾
  • db
    • 向后删除到上一个词开头
  • d0
    • 删除到本行行首
  • d^
    • 删除到本行第一个非空白字符
  • d$
    • 删除到行尾
  • dj / dk
    • 连同下一行 / 上一行形成删除范围
  • cw
    • 修改到下一个词开头
  • ce
    • 修改到词尾
  • c$
    • 修改到行尾
  • yw
    • 复制一个词范围
  • y$
    • 复制到行尾

operator 自己重复
#

  • dd
    • 删除整行
  • cc
    • 修改整行
  • yy
    • 复制整行

重复与放回
#

  • .
    • 重复上一次 change
  • p
    • 在光标后放回刚复制或删除的内容
  • P
    • 在光标前放回刚复制或删除的内容

它是怎么用的
#

核心心法:operator 负责“做什么”,motion 负责“做到哪里”
#

这是 Day 003 最重要的一句。

你可以把很多 Vim 编辑动作都理解成一个两段式结构:

  1. 先决定要做什么
  2. 再决定作用范围到哪里

例如:

  • d$
    • 我要删除
    • 范围到行尾
  • cw
    • 我要修改
    • 范围到下一个词开头
  • y0
    • 我要复制
    • 范围到行首

这和普通编辑器里“先选中,再点删除”有点像,但 Vim 把“选中范围”压缩成了 motion。

为什么 Day 002 的 motion 现在突然变得值钱
#

前一天学 we$ 的时候,可能会有一种感觉:

  • 我知道怎么过去了
  • 但好像还只是移动

到了今天,它们不再只是移动命令,而是范围描述语言。

比如:

  • w 不只是去下一个词头
  • 放在 d 后面,它变成“删到下一个词头”
  • 放在 c 后面,它变成“改到下一个词头”
  • 放在 y 后面,它变成“复制到下一个词头”

这就是 Vim 很核心的可组合性。

dcy 三者先分清职责
#

  • d
    • 删除文本,但不会自动进入插入模式
  • c
    • 删除这段文本,然后立刻进入插入模式,让你接着重写
  • y
    • 复制文本,本身不改内容

所以如果你的真实目标是“把这一段换成别的内容”,通常 cd 更顺手。

例如:

  • 想把一个词替换成别的词
    • 常常会优先想到 cw
  • 想把行尾整段说明改写
    • 常常会优先想到 c$
  • 想只是去掉某段内容,不立刻补字
    • 才更像 d

.:把“刚才那一下改动”变成可重复动作
#

D:\program\Learn-Vim\ch07_the_dot_command.md 补了一个非常实用的点:

  • . 重复的是上一次 change
  • 它不是“重复上一切按键”

本地 repeat.txt 也写得很直接:

  • .
    • Repeat last change

这在真实编辑里很值钱,因为你常常会遇到:

  1. 先用一次 cw...<Esc> 把第一个目标改对
  2. 移动到下一个相似位置
  3. 直接按 .

一个典型节奏就是:

  • /let
  • cwconst<Esc>
  • n
  • .

先改对一次,再重复,比每次都重新打一遍稳定得多。

双写 operator 时,范围会变成“整行”
#

本地帮助里的 operator 章节明确提到:

  • operator 重复一次,会按行工作

最常见的就是:

  • dd
  • cc
  • yy

这组命令非常高频,因为“整行”本身就是最常见的结构单位之一。

可以把它理解成:

  • 单个 operator 等你给范围
  • 双写 operator 直接把范围定成行

p / P:让复制和删除真正接成闭环
#

Day 003 里如果只学 y,还不够形成完整手感,因为复制之后往往马上就要放回。

本地 change.txt 里:

  • p
    • put 到光标后
  • P
    • put 到光标前

所以今天至少要把这几个最短闭环接上:

  • yy 然后 p
    • 复制一整行并在下面放回
  • yy 然后 P
    • 在上面放回
  • y$ 然后 p
    • 把当前到行尾的内容放到别处

你会开始感觉到:

  • y 不是“只是先复制一下”
  • 而是“先拿住这段内容,接下来随时可以 p / P 放回”

关于 cw:先把常用结论记住,不要一开始钻边角
#

初学时最容易纠结的是:

  • cw 到底是不是“改一个完整词”
  • 它和 ce 的边界有什么细小差异

今天先记一个够用结论:

  • 想把当前词或词的一部分改掉,优先试 cw
  • 想明确改到词尾,记住 ce

先把主力用顺,比一开始就钻所有边界更重要。等到文本对象阶段,再把“词内精确范围”讲细。

常见操作套路
#

套路 1:改一个词,不要手动删了再进插入
#

低效做法:

  1. 移动到词附近
  2. 进插入模式
  3. 按退格慢慢删
  4. 重打

更稳的方式:

  1. w / b 到目标词
  2. cw 直接改
  3. 输入新内容
  4. Esc 回普通模式

套路 2:删到行尾,用 d$,不要一路删字符
#

这个场景非常高频:

  • 删除注释尾巴
  • 删除一行后半段说明
  • 删除错误拼上的内容

这时直接:

  • d$

如果你是要“删掉并立刻重写”,就改成:

  • c$

套路 3:处理整行时,直接想 dd / cc / yy
#

遇到这些场景:

  • 这一行不要了
  • 这一行整句要重写
  • 这一行要复制到别处

优先想到的是整行 operator,而不是先移动到行首行尾再拼范围。

套路 4:相似修改先做对一次,再用 .
#

场景:

  • 同一类词要改两三处
  • 同一种尾巴要删几次

节奏通常是:

  1. 先在第一个位置把动作做对
  2. 移动到下一个位置
  3. . 重复

套路 5:先问自己是在“删”“改”还是“复制”
#

这是把 Vim 变顺手的关键自问:

  1. 这次我要做什么?
  2. 我要作用到哪里?

一旦这个两段式判断建立起来,你会更自然地写出:

  • dw
  • de
  • d$
  • cw
  • c$
  • yw

环境差异:vim / nvim / LazyVim
#

operator + motion 是 Vim 系编辑器的共同底层
#

本地 Vim 9.2 文档 motion.txt 里的 operator 章节说明:

  • motion 可以跟在 operator 后面
  • operator 和 motion 的 count 会相乘
  • 双写 operator 会变成按行操作

本地 Neovim 0.12.0 的运行时文档 change.txt 也保留了同一套 operator 行为。

所以今天学到的不是某个配置流派技巧,而是整个 Vim 家族的底层语法。

到了 LazyVim,这套语法只会更重要,不会被替代
#

LazyVim 会给你更强的:

  • 文件查找
  • 项目搜索
  • LSP 跳转
  • buffer 工作流

但进到文件以后,真正改内容时,仍然大量依赖今天这套两段式动作。

如果 Day 003 不稳,到了 LazyVim 常见的结果是:

  • 文件找得很快
  • 跳转很快
  • 但具体修改还是回到低效手工编辑

今日练习(5-10 分钟)
#

练习材料
#

新建一个临时文件,写入下面内容:

TXT 代码 · 共 5 行
vim makes editing composable
I want to change words instead of retyping whole lines
delete to end should feel natural
copying useful parts should also stay in normal mode
change this change that

练习任务
#

  1. vimnvim 打开这个文件。
  2. 在第一行把 editing 改成 changes,优先使用 cw
  3. 在第二行把 whole lines 改成 sentences,先移动到目标区域,再用 c 组合完成。
  4. 在第三行从 to 开始删到行尾,使用 d$
  5. 在第四行复制从光标处到行尾的内容,使用 y$,然后找一个位置试 pP
  6. 在最后一行把第一个 change 改成 edit,再移动到第二个 change,用 . 重复上一次修改。
  7. 单独试一次:
    • dd
    • yy
    • cc
  8. 每做完一步都按 Esc 回到普通模式,观察自己是不是在“先决定操作,再给范围”。

完成标准
#

  • 能用一句话说清楚:
    • operator 决定做什么,motion 决定做到哪里
  • 能在至少三个真实动作里自然用出组合:
    • dw / d$
    • cw / c$
    • yy / y$
  • 能把 . 当成“重复上一次修改”,而不是重新打一遍。
  • 能用 p / P 把复制和删除动作接成闭环。
  • 不再总是通过“进插入模式后手工删改”来完成所有编辑

今日问题与讨论
#

我的问题
#

问题 1:为什么要把编辑拆成 operator + motion,而不是直接背很多独立命令?
#

  • 简答:
    • 因为这样更统一,也更容易组合。
  • 场景:
    • 你已经学过 w$0 这些 motion,现在不需要为“删到词尾”“改到行尾”“复制到行首”分别背新命令。
  • 依据:
    • 本地 motion.txtoperator 章节明确说明,motion 可以跟在 operator 后面形成操作范围。
  • 当前结论:
    • Vim 的效率不只来自命令数量,更来自语法式组合。
  • 是否需要后续回看:

问题 2:dc 到底怎么选?
#

  • 简答:
    • 删掉但暂时不重写,用 d;删掉并立刻改写,优先用 c
  • 场景:
    • 改变量名、改注释尾巴、重写半句文本。
  • 依据:
    • 本地实际行为里,c 在删除目标范围后会进入插入模式,d 不会。
  • 当前结论:
    • 真实目标是“替换”时,c 常常比 d 更顺。
  • 是否需要后续回看:

问题 3:为什么 ddccyy 这么常用?
#

  • 简答:
    • 因为“整行”本身就是很常见的编辑单位。
  • 场景:
    • 删除整行日志、重写整行注释、复制整行配置。
  • 依据:
    • 本地帮助 operator 章节说明,operator 双写时按行工作。
  • 当前结论:
    • 看到“整行”场景时,先想双写 operator。
  • 是否需要后续回看:

外部高价值问题
#

问题 1:为什么 . 有时没把我刚才整套操作都重放出来?
#

  • 问题:
    • 我明明刚才做过“移动一下再删”这整套动作,为什么 . 只重复了其中的改动部分?
  • 简答:
    • 因为 . 重复的是上一次 change,不是单纯的移动本身。
  • 场景:
    • f,x,然后想直接用 . 完整重放“找逗号再删”。
  • 依据:
    • 本地 repeat.txt
    • D:\program\Learn-Vim\ch07_the_dot_command.md
  • 当前结论:
    • 把“会改内容的那一下”做成一个完整 change,. 才最值钱;单纯移动需要你自己再给一次。
  • 是否需要后续回看:

常见误区或易混点
#

  • 误区 1:学了 operator + motion 就等于要背更多命令
    • 不是。它反而是在减少孤立命令数量。
  • 误区 2:d 是万能主力,所有修改都先删再说
    • 真正要替换内容时,c 往往更贴合目标。
  • 误区 3:移动和编辑是两套分开的知识
    • 不是。motion 一旦接到 operator 后面,就成了编辑范围。
  • 误区 4:双写 operator 只是“快捷写法”
    • 它不仅省按键,还表达了“整行”这个高频单位。
  • 误区 5:今天就要把 cw 的所有边界完全吃透
    • 先掌握高频结论和手感,细边界可以放到后续文本对象和专项回看里。

扩展内容
#

  • {count} 可以同时作用在 operator 和 motion 上
    • 例如帮助里给出的 2d3w 会删除六个词。
  • D
    • 常可理解成删到行尾,和 d$ 在很多场景里接近。
  • C
    • 常可理解成改到行尾,和 c$ 在很多场景里接近。
  • :reg
    • 查看当前寄存器内容,帮助你把复制、删除、粘贴和寄存器联系起来。
  • "" / "0 / "_
    • 分别是默认寄存器、最近一次 yank、黑洞寄存器;先知道这三个就很够用。

今日小结
#

Day 003 真正要建立的是一个新的编辑句式:

  • 先决定做什么
  • 再决定做到哪里

一旦这句式建立起来,Day 002 的移动就不再只是“移动技巧”,而是开始真正变成编辑能力。

明日衔接
#

下一步建议进入:

  • Day 004:文本对象

重点会开始解决:

  • 为什么“一个词里面”或“括号里面”也可以被当成稳定范围
  • 为什么 operator + motion 之后,文本对象会让编辑范围更贴合结构
  • 为什么 ci(di" 这类动作会让修改代码和文本更自然

复习题
#

  1. operatormotion 分别负责什么?
  2. 为什么说 Day 002 的移动到了今天才真正接上编辑?
  3. dc 的核心差别是什么?
  4. d$cwy$ 分别在做什么?
  5. 为什么 ddccyy 应该优先被当成高频动作记住?
Vim 14 天 - 这篇文章属于一个选集。
§ 3: 本文