对于vi的初学者,宏命令听起来像是高阶魔法,往往敬而远之。但当你面对几十个需要格式化的日志文件,或者需要将几百行数据批量转换成SQL语句时,你才会真正体会到,宏不是“炫技”,而是把你从重复劳动的泥潭里拽出来的救命绳索。
vi的宏本质上是把一连串按键操作录制下来,并存入一个“寄存器”里。命令很简单:在普通模式下按q,紧接着按一个字母(比如a)来指定寄存器,这时屏幕下方通常会显示“recording”提示。之后你做的所有操作——移动、删除、插入、替换——都会被忠实记录。完成后,再按一次q结束录制。
调用它更简单:在普通模式下按@a(假设你存入了寄存器a),刚才录制的操作就会原样重放一次。这个“记录-调用”的循环,构成了宏效率的基石。
很多人不敢用宏,是怕录错了改不了。其实,vi的寄存器是“可擦写”的。如果你对录在a里的宏不满意,随时可以再按qa重新录制,新的内容会直接覆盖旧的。这种设计鼓励你大胆尝试,因为成本几乎为零。
录制宏时最常犯的错误,是录制了包含绝对位置的操作。比如,你从当前行行首删除5个字符,宏会忠实地记录“删除行首5个字符”。但如果下一行的行首结构不同,宏就会执行失败。
高手的做法是,让宏基于相对位置和文本对象来操作。例如:
dw(删除一个词)代替d5l(删除右边5个字符)。f,(跳转到下一个逗号)代替多次按l(右移)。ci"(修改引号内的内容)代替进入插入模式再手动删除。这样的宏适应性更强,能在结构相似但长度不一的内容上稳定工作。
假设你录好了一个宏a,它能完美处理一行数据。现在有100行需要处理,难道要按100次@a吗?当然不用。
你可以在调用前加数字前缀:100@a。更酷的是,vi记住了你最后一次调用的宏。所以当你按了一次@a后,只需要疯狂地按@@,就能重复执行上一次的宏命令,速度快得像在打街机。
假设你有一个纯文本列表:张三,30,工程师,需要转换成SQL插入语句:('张三', 30, '工程师')。
你可以这样录制宏q:
(‘:I('', :f,s', , ':f;s, '')并换行:A')<Esc>j录制完成后,回到第一行,执行99@q(假设有100行)。一瞬间,所有行都转换完毕。这种从枯燥手工劳动中解放出来的快感,是任何图形化工具“查找替换”难以比拟的。
宏执行出错了怎么办?别急着重录。你可以用:reg a(查看寄存器a的内容)来“复盘”你录制的按键序列。你会发现,宏其实就是一串普通的vi命令字符。理解这一点,你就能像阅读代码一样调试你的宏。
说到底,vi宏的高效,不在于命令本身有多复杂,而在于你如何将重复的模式抽象成一套精确的指令。它逼迫你去更深入地理解文本的结构,而不是机械地移动光标。当你开始习惯用宏的思维看待文本编辑时,那些曾经令人望而生畏的批量任务,会变成一种指尖上的、带着节奏感的愉悦操作。
参与讨论
录宏的时候老是忘按q结束,有没有人和我一样的?
之前处理日志文件全靠手动,看完才意识到自己蠢了好久
这个宏调试方法绝了,刚试完直接省了半小时手操👍
用f,跳转比一直按l舒服太多,这点真是点醒我了
100@a这个操作也太爽了吧,像在写自动化脚本hhh