Vim 学习 - 快速删除/修改

前言

之前用 Vim, 遇到字符串的修改时, 基本是

进入编辑Backspace慢慢删 / 估计字符串长度 nx 一点点删

其实它还是有更便捷的操作方式

本文对 Vim 文本 删除/修改 做一点讲解。

正文

来系统讲一下 Vim 中**删除(delete)修改(change)**的常用操作。

核心规律是:

vim 复制代码
操作符 + 范围

最常见操作符:

vim 复制代码
d    删除(delete)
c    修改(change):删除后自动进入插入模式
x    删除单个字符
s    删除单个字符后进入插入模式

例如:

vim 复制代码
di"    删除双引号内部
ci"    修改双引号内部

两者的区别只是:c 会在删除后直接进入插入模式。


1. 引号、括号中的修改与删除

假设有:

js 复制代码
const message = "this is a very long text";

光标只要位于双引号内容中的任意位置。

保留引号,只删除内容

vim 复制代码
di"

结果:

js 复制代码
const message = "";

iinner(内部),所以不包含外围的引号。


保留引号,修改内容

vim 复制代码
ci"

结果会先变成:

js 复制代码
const message = "";

并自动进入插入模式。输入新内容:

text 复制代码
Hello Vim

再按 Esc,得到:

js 复制代码
const message = "Hello Vim";

这是编辑字符串时最常用的命令之一。


引号也一起删除

vim 复制代码
da"

aaround(连同外围一起)。

js 复制代码
const message = "this is a very long text";

执行 da"

js 复制代码
const message = ;

通常在你想移除整个字符串表达式时使用。


各种成对符号都适用

vim 复制代码
di'     " 删除单引号内部
ci'     " 修改单引号内部
da'     " 删除单引号及内容

di`     " 删除反引号内部
ci`     " 修改反引号内部

di(     " 删除小括号 () 内部
ci(     " 修改小括号 () 内部
da(     " 连 () 一起删除

di[     " 删除方括号 [] 内部
ci[     " 修改方括号 [] 内部
da[     " 连 [] 一起删除

di{     " 删除花括号 {} 内部
ci{     " 修改花括号 {} 内部
da{     " 连 {} 一起删除

括号通常也可使用对应的另一种写法:

vim 复制代码
di)     " 等同于 di(
di]     " 等同于 di[
di}     " 等同于 di{

例如:

python 复制代码
process(user_id, verbose=True)

光标在括号内部时:

vim 复制代码
ci(

会保留 (),清空参数并进入插入模式:

python 复制代码
process()

2. 修改、删除当前单词

假设内容是:

text 复制代码
The quick brown fox

光标位于 quick 的任何位置。

删除当前单词

vim 复制代码
diw
  • i:inner
  • w:word

结果:

text 复制代码
The  brown fox

注意:它只删除单词本身,可能留下两个空格。


删除单词以及一个相邻空格

vim 复制代码
daw
  • a:around word

结果通常更符合删除"一个词"的预期:

text 复制代码
The brown fox

修改当前单词

vim 复制代码
ciw

删除 quick 并进入插入模式。输入 slow 后:

text 复制代码
The slow brown fox

ciw 是日常代码编辑里使用频率极高的一条。


cwciw 的区别

很多人会把它们混用,但有一个细微差异。

vim 复制代码
cw

表示"从光标当前位置修改到单词末尾"。

vim 复制代码
ciw

表示"修改完整的当前单词"。

例如:

text 复制代码
hello
  ^

光标在 l 上:

vim 复制代码
cw

只会删除 llo

vim 复制代码
ciw

会删除整个 hello

所以想稳定地替换整个单词,优先用:

vim 复制代码
ciw

3. 从当前位置删到某个位置

除了文本对象,你也可以将删除/修改和移动命令组合。

基本形式:

vim 复制代码
d + 移动命令
c + 移动命令

例如:

vim 复制代码
dw      " 从光标删除到下一个单词开头
de      " 从光标删除到单词末尾
db      " 向前删除到上一个单词开头

d$      " 删除到行尾
d0      " 删除到行首(包括行首空白)
d^      " 删除到第一个非空白字符

修改版本:

vim 复制代码
cw      " 修改到下一个单词开头
ce      " 修改到单词结尾
cb      " 向前删除到上一个单词开头后,进入插入模式

c$      " 修改到行尾
C       " 等同于 c$

一些直观示例

内容:

js 复制代码
const total = calculatePrice(items, discount);

光标位于 calculatePrice 中间。

vim 复制代码
ciw

直接替换整个函数名。

光标在 items 上:

vim 复制代码
ci(

删除整个参数列表内容,保留括号:

js 复制代码
const total = calculatePrice();

光标在等号右边,想清空这一行后半段:

vim 复制代码
d$

结果:

js 复制代码
const total =

想删掉后半段并立即输入新表达式:

vim 复制代码
C

输入:

js 复制代码
getTotal(cart);

得到:

js 复制代码
const total = getTotal(cart);

4. 按字符查找后删除/修改

这是行内编辑非常高效的一组。

vim 复制代码
f{字符}    跳到右侧下一个字符
t{字符}    跳到右侧下一个字符之前
F{字符}    向左找字符
T{字符}    向左跳到字符之后

它们可以和 dc 组合。

例如:

text 复制代码
name: value, next: another
^ 光标在 n

删除到逗号,但不删逗号

vim 复制代码
dt,

结果:

text 复制代码
, next: another

d + t,:删除到逗号的前一个位置。


删除到逗号,包含逗号

vim 复制代码
df,

结果:

text 复制代码
 next: another

修改到逗号前

vim 复制代码
ct,

先删除 name: value,然后进入插入模式,逗号保留。

这对修改 CSV、函数参数、对象字段、链式调用的一段内容很实用。


重复查找

vim 复制代码
;       " 重复最近一次 f / t / F / T
,       " 反向重复最近一次 f / t / F / T

例如:

vim 复制代码
f,
;       " 跳到下一个逗号
;       " 再跳到下一个逗号

5. 整行和多行删除、修改

当前行

vim 复制代码
dd      " 删除当前行
cc      " 删除当前行并进入插入模式
yy      " 复制当前行

也可以用:

vim 复制代码
D       " 从光标删到行尾
C       " 从光标修改到行尾
S       " 等同于 cc

指定数量的行

vim 复制代码
3dd     " 删除当前行及其后两行,共 3 行
5cc     " 删除 5 行并开始编辑
4yy     " 复制 4 行

删除到文件开头 / 结尾

vim 复制代码
dgg     " 从当前位置删除到文件开头
dG      " 从当前位置删除到文件结尾

修改范围也可以:

vim 复制代码
cG      " 删除当前位置到文件结尾,然后进入插入模式

不过这种操作范围大,使用前建议确认一下光标位置。


6. 选择后删除或修改

可视模式适合范围不规则、但你能直接看到并选中的内容。

vim 复制代码
v       " 字符级选择
V       " 行级选择
Ctrl-v  " 块选择(列选择)

选中后:

vim 复制代码
d       " 删除选中内容
c       " 删除并进入插入模式
x       " 删除
y       " 复制

例如:

  1. v
  2. 移动光标选中一段;
  3. d 删除。

块选择:批量删列、改多行

例如代码:

js 复制代码
const first = 1;
const second = 2;
const third = 3;

如果要删掉每一行前面的 const

  1. 光标放到第一行 c
  2. Ctrl-v
  3. 向下选择三行;
  4. 向右选中 const 的宽度;
  5. d

批量添加前缀:

  1. Ctrl-v 选中多行的第一列;
  2. I(大写 i);
  3. 输入 //
  4. Esc

批量修改行尾:

  1. Ctrl-v 选中多行;
  2. A(大写 a);
  3. 输入内容;
  4. Esc

7. 常用文本对象清单

文本对象是 Vim 删除和修改的精髓。

操作目标 删除内部 修改内部 删除整体
当前单词 diw ciw daw
双引号内容 di" ci" da"
单引号内容 di' ci' da'
小括号内容 di( ci( da(
方括号内容 di[ ci[ da[
花括号内容 di{ ci{ da{
HTML 标签内容 dit cit dat
当前句子 dis cis das
当前段落 dip cip dap

例如 HTML:

html 复制代码
<a href="/docs">Read documentation</a>

光标位于文字部分时:

vim 复制代码
cit

删除 Read documentation 并进入插入模式,但保留标签:

html 复制代码
<a href="/docs"></a>

如果用:

vim 复制代码
dat

则整个 <a ...>...</a> 都会删掉。


8. 删除单字符、替换单字符

vim 复制代码
x       " 删除光标所在字符
X       " 删除光标前一个字符

s       " 删除当前字符并进入插入模式
r{字符} " 替换当前字符,例如 rx:替换为 x
R       " 连续覆盖输入(Esc 退出)

示例:

text 复制代码
helo
   ^

光标在第二个 l 后面的 o 前,想补一个 l

vim 复制代码
i

即可。

如果当前字符写错了:

text 复制代码
helo
   ^

光标在 o 上,执行:

vim 复制代码
ra

会得到:

text 复制代码
hela

如果要将一个字符替换为一个较长文本:

vim 复制代码
s

删除当前字符并进入插入模式。


9. 删除不想覆盖剪贴板的内容

默认 dddx 删除的内容会存入 Vim 寄存器,因此会覆盖你刚复制的内容。

场景:

  1. 你先 yy 复制了一行;
  2. 之后想删除几行垃圾内容;
  3. 最后还想 p 粘贴刚才复制的那一行。

可以把无用删除送到"黑洞寄存器":

vim 复制代码
"_d
"_dd
"_di"
"_ciw

例如:

vim 复制代码
"_dd

删除当前行,但不影响你此前复制的内容。


10. 删除后粘贴:替换选中内容

一个很实用的技巧:

vim 复制代码
v{选择内容}p

在可视模式中按 p,会用最近复制的内容替换当前选中区域。

例如:

  1. yiw 复制单词 A;
  2. 移到单词 B;
  3. viwp 选中 B 并用 A 替换。

在较新的 Vim/Neovim 中,这通常还会保留原先的复制内容,方便连续替换;如果你的版本/配置行为不同,想确保复制内容不受影响,可在替换前重新复制,或使用寄存器保存。


11. 结合搜索进行删除和修改

假设文件里有许多 debug

vim 复制代码
/debug

找到一个后:

vim 复制代码
ciwproduction<Esc>

将其改为 production

接下来:

vim 复制代码
n
.
  • n:找下一个 debug
  • .:重复上一次修改

这比逐次输入 ciwproduction 快得多。

类似地,删除多个搜索结果附近内容时也可以:

vim 复制代码
/temporary
diw
n
.

. 会重复最近一次可重复的修改操作。


12. 最值得先练成肌肉记忆的删除/修改命令

vim 复制代码
x           删除一个字符
dd          删除一行
D           删除至行尾

dw          删除到下一个单词
de          删除到单词末尾
d$          删除到行尾

ciw         修改当前单词
diw         删除当前单词
daw         删除单词及邻近空格

ci"         修改双引号内内容
di"         删除双引号内内容
da"         删除整个双引号字符串

ci(         修改括号内内容
ci{         修改代码块内容
di{         清空代码块

dt, / df,   删除到逗号前 / 删除到逗号(包含逗号)
ct,         修改到逗号前

u           撤销
Ctrl-r      重做
.           重复上一次修改

可以把 Vim 的编辑思路概括为:

vim 复制代码
我想删除什么?         d
我想删除后立刻重写?    c
范围是单词?            iw / aw
范围是引号内部?        i"
范围是括号内部?        i(
范围是到某个字符?      t{字符} / f{字符}
范围是到行尾?          $

所以当你看到:

js 复制代码
sendEmail(user, "old subject", body);

光标在 "old subject" 内时,几乎不需要移动,直接:

vim 复制代码
ci"

输入新标题即可。这正是文本对象让 Vim 高效的地方。

相关推荐
小黄人软件1 小时前
如何解决不想学、学不会、学不进去,吸收内化不了学的东西,怎么办?如何真正建立“知识内化系统“?不输出,不学习
学习
个 人 练 习 生2 小时前
strcmp与strstr函数的模拟实现
c语言·开发语言·经验分享·学习·程序人生
晓梦林3 小时前
[ACTF2020 新生赛]BackupFile学习笔记
android·笔记·学习
2601_963870173 小时前
【计算机毕业设计】基于Spring Boot的社区老年大学课程报名与学习系统的设计与实现
java·spring boot·学习
xian_wwq4 小时前
【学习笔记】解剖 Claude Code —— Anthropic 的 Harness 参考实现-09/15
人工智能·笔记·学习
其实防守也摸鱼4 小时前
Kimi K3深度测评:长文本之外的真实力
运维·开发语言·网络·人工智能·python·学习·安全
晓梦林5 小时前
Tools靶场学习笔记
笔记·学习
xian_wwq5 小时前
【学习笔记】什么是Harness Engineering- 01/15
人工智能·笔记·学习
xian_wwq6 小时前
【学习笔记】Agent 安全护栏 —— 当 Agent DROP TABLE 了你的生产数据库-07/15
笔记·学习·安全