写在前面
Vim 宏这部分知识点不仅讲解起来篇幅最长,同步练习环节的作业量也是全套课程中最多的。宏在 Vim 操作中不可撼动的核心地位由此可见一般。虽然今天有事耽搁了笔记整理,到家后的第一件事仍然是一步一个脚印地先在本地做一遍所有习题,然后再对照讲义完成翻译。这个过程不可能很快,但也是掌握 Vim 宏相关要点不可或缺的重要环节。我用自己的亲身经历奉劝各位,切忌急于求成,尤其不要在该筑牢基础的地方吝惜自己的时间和精力。要相信水滴石穿的力量,相信玉汝于成,功不唐捐。同步练习中列举的几个典型案例值得大家反复琢磨与演练。
练习 Vim
中的宏(macro
)的创建与使用。1
用 Vim
打开源码包内的练习文件 macros-practice.txt
(默认解压到 Downloads
文件夹下):
cd Downloads
cd vimclass
vim macros-practice.txt
给定一组旧版 Python 代码(v2.6
及以前版本),试将其改为新版写法(v3.0
即以上版本):将 print
语句改为 print()
函数。也就是说,需要对以下各行作如下处理——
由修改前的:
print "Macros are very fun!"
统一改为:
print("Macros are very fun!")
下面用 Vim
宏来实现。顺便提一下,本练习无需了解 Python
语法,本例旨在提供一个实际案例来练习 Vim
宏的相关操作。
其中一种参考方案实现如下:
print "Macros are very fun!"
"a
;Vim
宏快速重复操作;要查看寄存器 "a
中的录制内容,可输入命令 :reg a
+ Enter。内容如下:
"a 0f r(A)^[j
键入 @A 即可对下一行运行录好的宏;若要重复执行上一次宏操作,按 @@ 即可。余下各行均可使用 @@ 重复宏的运行。
注意
上述实现仅供参考,并非唯一的解决方案。例如将 FSpace 改为 T",也能将光标定位到同一处空格。只要能实现最终的效果就行。
给定一个用户列表,要求对列表中的每个用户分别执行一组相同的操作。为此,可以将某个用户的一系列操作录制为一个 Vim
宏,然后对其余用户执行这个宏即可。最终目标是将如下这段文本:
jason
sophia
jack
emma
ava
统一改为以下形式:
passwd -l jason && echo jason >> locked_users.txt
passwd -l sophia && echo sophia >> locked_users.txt
passwd -l jack && echo jack >> locked_users.txt
passwd -l emma && echo emma >> locked_users.txt
passwd -l ava && echo ava >> locked_users.txt
这组命令用户锁定 Linux
系统中的指定用户帐号,并将其帐号名追加到一个 locked_users.txt
文件中。命令的含义无关紧要,关键在于 Vim
的用法。本练习旨在提供一个实际的应用场景。
其中一种参考方案实现如下:
jason
这一行;"b
;passwd -l
+ Escape;&&
+ Space + echo
+ Space + Escape 返回正常模式;>>
+ Space + locked_users.txt
,再按 Escape 切回正常模式;要查看寄存器 "b
中的录制内容,可输入命令 :reg b
+ Enter。内容如下:
"b yawIpasswd -l ^[A && echo ^[pa >> locked_users.txt^[j
对下一行执行宏操作,输入 @B 即可;后面三个类似的文本行,则可以用 3@B 轻松实现批量修改。
接下来,创建一个 Vim
宏并存入寄存器 "p
,实现将如下所示的电话号码:
2798265253
统一转换为符合美国人书写习惯的格式:
(279) 826-5253
其中一种参考方案实现如下:
2798265253
这一行(即待批量处理的第一行);"p
;(
,并按 Escape 回到正常模式;9
处;6
的下方;要查看寄存器 "p
中的录制内容,可输入命令 :reg p
+ Enter。内容如下:
"p I(^[llla) ^[llla-^[j
鉴于要处理的电话号码很多,文本行超出了屏幕,难以轻易获知需要重置执行多少次宏;此外,单纯使用 @@
来重复执行也很费时间。此时应该使用指定具体范围来应用宏操作。先用 :set nu
开启行号,再将光标定位到第 25 行;然后按 Ctrl + F 向下翻页,确定最后一个电话号码的行号为 73。
接着输入 :25,73 normal @p
+ Enter,通过 normal
命令指定具体范围并批量运行宏操作。之后再通过 Ctrl + B 上翻查看宏的执行情况。
下一组练习取材自 Linux
服务器的系统日志。这些内容是本地 Linux
防火墙阻止连接请求的日志记录。我们的目标是分别提取出时间戳、尝试连接的源 IP 地址以及目标端口。
其中,SRC=
字样后的内容即为源 IP 地址,例如:SRC=190.18.193.152
。
目标端口则位于 DPT=
字样后,例如:DPT=23
。
也就是利用 Vim
宏(假设录制到寄存器 "l
)将下面这样的日志内容:
Jan 13 09:57:01 www1 kernel: [3947771.808744] [BLOCK] IN=eth0 OUT= MAC=e6:e9:2d:04:b6:95:3c:8a:b0:0d:6f:f0:08:00 SRC=190.18.193.152 DST=2.5.9.1 LEN=40 TOS=0x02 PREC=0x00 TTL=51 ID=25120 PROTO=TCP SPT=12502 DPT=23 WINDOW=4078 RES=0x00 SYN URGP=0
批量精简为如下版本,并以逗号分隔:
Jan 13 09:57:01,190.188.193.152,23
其中一种参考方案实现如下:
Jan 13 09:57:01
开头的这一行;"l
;dtS
删除当前光标到 SRC=
之间的所有内容;SRC
;=
替换为逗号 ,
;d/DPT
+ Enter 删除当前光标与 DPT=
之间的文字内容;DPT
;=
替换为逗号 ,
;要查看寄存器 "l
中的录制内容,可输入命令 :reg l
+ Enter。内容如下:
"l 0twdtSdwr,f d/DPT^Mdwr,f Dj
同样,还有其他方式可以实现上述任务。例如,要将 SRC=
改为 ,
,除了用上面的 DWR 实现,还可以使用 2CW。不妨停下来思考一下类似的备选方案对录制的宏进行修改,看看能否达到同样的效果。
若要对下一行日志执行录制的宏,输入 @L 即可。如果没问题,就用 @@ 重复执行,直至处理完剩下的日志内容。
再次强调,宏录制的是一系列按键操作。尽管我们一直在单行内容上练习宏的相关操作,宏也可以作用于多行。假如需要将下列三行通过录制的宏(假设存入寄存器 "c
)按要求处理为一行,即从之前的:
Country China
1,380,950,000 people
处理为:
1,380,950,000;China
其中一种参考方案实现如下:
Country China
开头的这一行;"c
;Country
;要查看寄存器 "c
中的录制内容,可输入命令 :reg c
+ Enter。内容如下:
"c 0dwjdWkPr;j2dd
接着,可以通过引入数量词,即 4@C,将上述宏操作再重复执行四次,实现该组数据的批量处理。
同样,要在 Vim
中实现上述效果还有很多其他方案可供选择。
<a href="#">@armyspy.coma><a href="#">@cuvox.dea><a href="#">@dayrep.coma><a href="#">@einrot.coma><a href="#">@fleckens.hua><a href="#">@gustr.coma><a href="#">@jourrapide.coma><a href="#">@rhyta.coma><a href="#">@superrito.coma><a href="#">@teleworm.usa>
最终需要通过 Vim
宏(假设存入寄存器 "q
)处理成下列效果:
armyspy.com
cuvox.de
dayrep.com
einrot.com
fleckens.hu
gustr.com
jourrapide.com
rhyta.com
superrito.com
teleworm.us
其中一种参考方案实现如下:
开头的文本行;
"q
;@
之间(包含 @
)的所有内容;<
位置;
替换为一个换行标记;要查看寄存器 "q
中的录制内容,可输入命令 :reg q
+ Enter。内容如下:
"q df@f
输入 @Q 即可运行这个宏。继续重复执行,按 @@ 即可,直至处理完其余链接内容。
若要放弃文件变更以便下次重新练习,使用退出命令 :q!
+ Enter。
本节为同步练习点评课,视频本身没有增补知识点。这里仅对实操过程中的几个问题进行复盘:
@{macro_name}
的形式运行宏;
时选择了先删除
再用 I 键插入一个回车符。处理到最后一个链接时,由于闭标签后没有下一个
,再用 I 键插入回车符会让最后一个字符 s
与前面的内容分离。既然是批量操作,就应当一气呵成,切忌在这样的临界点位置拖泥带水。本节练习另附精美排版 PDF 格式,阅读体验更佳,详见:vimclass/Exercise-09-Macros.pdf
↩︎