技巧26 在长短不一的高亮块后添加文本
列块可视模式在操作由行列组成的方形代码块时表现得很好,然而,它并不仅限于操作方形的文本区域.
举例:
var foo = 1;
var bar = 'a' ;
var foobar = foo + bar;
这段代码中有连续3行,每行的长度各不相同,我们想在每行的结尾添加一个分号.在技巧2中,我们使用了.命令解决了此问题,不过用列块可视模式也可以完成该任务.
在进入列块可视模式后,我们按$键把选取扩大到每行的行尾,在这个场景中,vim知道我们是想把选取扩大到所选中的那些行的结尾,它会让我们打破方形的限制,创建出一个右边界长短不一的文本选区.
确定好选区之后,用a命令可以在每行的行尾添加内容.
<c-v> jj$
a;
<esc>
vim 对于’i’及’a’键的约定
vim对于从普通模式切换到插入模式的命令有几个约定,i命令和a命令都完成此切换,并把光标置于当前字符之前或之后. i命令和a命令的表现类似,只是它们分别把光标置于当前行的开头和结尾.
vim对于从列块可视模式切换到插入模式的命令也遵从类似的约定.i命令和a命令都完成此切换,并分别把光标置于选区的开头和结尾.那i和a命令呢,他们在可视模式里面干什么?
在可视模式及操作符待决模式中,i和a键沿用了一个不同的约定,它们会被当做一个文本对象的组成部分.如果在列块可视模式中选中了一块区域,很奇怪为什么按i没有进入插入模式,换用i键试一下.
命令行模式
技巧27 结合vim的命令行模式
在按下:键时,vim会切换到命令行模式,这个模式和shell下的命令行有些类似,我们可以输入一条命令,然后按执行它.在任意时刻,我们都可以按<esc>键从命令行模式切换回普通模式.
我们可以按/调出查找提示符或用<c-r>=访问表达式寄存器,命令行模式也会被激活.
我们可以用ex命令读写文件(:edit 和 :write),创建新标签页(:tabnew)及分割窗口(:split),或是操作参数列表(:prev/:next)及缓冲区列表(:bprev/:bnext).事实上,vim几乎为所有的功能都提供了相应的ex命令.
| 命令 | 用途 |
|---|---|
| :[range]delete[x] | 删除指定范围内的行(到寄存器x中) |
| :[range]yank[x] | 复制指定范围的行(到寄存器x中) |
| :[line]put[x] | 在指定行后粘贴寄存器x中的内容 |
| :[range]copy{address} | 把指定范围内行拷贝到{address}所指定的行之下 |
| :[range]move{address} | 把指定范围内行拷贝到{address}所指定的行之上 |
| :[range]join | 连接指定范围内的行 |
| :[range]normal | {commands} 对指定范围内的每一行执行普通模式命令{commands} |
| :[range]substitute/{pattern}/{string}/{flags} | 把指定范围内出现{pattern}的地方换乘{string} |
| :[range]global/{pattern}/[cmd] | 对指定范围内匹配{pattern}的所有行,在其上执行ex命令{cmd} |
vim命令行模式中的特殊按键
有些命令在插入模式和命令行模式中可以通用.例如:可以用<c-w>和<c-u>分别删除至上个单词的开头及行首,也可以用<c-v>或<c-k>来插入键盘上找不到的字符,还可以用{register}命令把任意寄存器中的内容插入到命令行.然而,有些命令行模式中的组合键在插入模式中不存在.
<left>和<right>光标键可以一次把光标向左或向右移动一个字符.
ex命令影响范围广且距离远
技巧28 在一行或多个连续行上执行命令
很多ex命令可以用[range]指定要操作的范围,我们可以用行号,位置标记或查找模式来指定范围的开始位置及结束位置.
ex命令的优点之一是它们可以在某一范围内的所有行上执行,我们以下面这个简短的html文本作为示例:
<!doctype html>
<html>
<head><title>practical vim</title></head>
<body><h1>practical vim</h1></body>
</html>
如果我们使用:print命令作为演示,这条命令只能简单的在vim命令行下方回显指定行的内容,不会产生什么实际影响,不过可以用它来说明一个范围由那些行构成.当然,你可以试着把一下示例中的:print换成诸如:delete,:join,:substitute或者:normal这样的命令,这样就能真切地体会到ex命令是多么有用.
用行号作为地址.
:1 就是跳转到第一行
:print 就是打印 和:p效果一样
:跳转到最后一行:p打印:.,p 就是从当前行打印到文件末尾
:%p 它代表当前文件中的所有行
:%s/practical/pragmatic/ 上述命令让vim把每一行第一个”practical”替换为”pragmatic”.
用高亮选取指定范围
我们可以用高亮选区选定应该范围,而不是用数字指定,如果我们先执行2g,再跟着执行vg,就会选中如下一个高亮选区:
如果我们先执行2G,再跟着执行VG,就会选中如下一个高亮选区:
如果现在按下:键,命令行上就会预先填充一个范围:’<,’> 这个范围看起来有点晦涩难懂,我们可以简单的把它理解为一个代表高亮选区的范围.接下来我们就可以输入一条ex命令,使它在每个被选中的行上执行:
:’<,’>p 就是打印选中的部分
如果只是想对文件的部分内容执行:substitute命令,用这种方式定义范围会很方便.
符号’< 是代表高亮选区首行的位置标记,而’>则代表高亮选区的最后一行,这些位置标记即使退出可视模式后仍然存在,如果你尝试在普通模式下直接运行:’<,’>p,他会始终回显上一次高亮选区所选中的内容.
用模式指定范围
:/<html>/,/\/<html>/p
这个范围看起来比较复杂,但实际上它符合范围的一般形式:{start},{end}.在本例中,{start}地址是//,而{end}地址是/<\/html>/.换句话说,这个范围由<html>开标前所在的行开始,到对应闭标签所在行结束.
用偏移对地址进行修正
假设我们想对<html></html>之间的每一行都运行一条Ex命令,但是不想包括<html>及</html>标签所在的行,那么可以为之加上偏移:
:/<html>/+1,/\/html>/-1p
偏移的一般形式是这样的:
:{address}+n
如果n被忽略,那么缺省偏移量为1.{address}可以是一个行号,一个位置标记,或是一个查找模式.
假设我们想对由当前行开始的指定几行执行一条命令,那么就可以使用相对于当前行的偏移:
:2
:.,.+3p
符号点代表当前行,所以上例中的:.,.+3相当于:2,5
结论:
定义范围的语法非常灵活,既可以混合搭配行号,位置标记以及查找模式,也可以对它们加上偏移,下表对用来构建Ex命令的地址及范围的符号进行了总结:
1 文件的第一行
$ 文件的最后一行
0 虚拟行,位于文件第一行上方
. 光标所在行
‘m 包含位置标记m的行
‘< 高亮选区的起始行
‘> 高亮选区的结束行
% 整个文件
技巧29 使用:t 和 :m 命令复制和移动行
:copy命令(简写形式是:t)可以让我们把一行或多行从文档的一部分复制到另一部分,而:move命令则可以让我们把一行或者多行移动到文档的其他地方.
:6copy. 命令解读为”为第六行创建一个副本,并放到当前行下方”
:copy 命令可以简写为:co 或者也可以用更加简练的:t命令,它是:copy命令的同义词.
:6t. 把第六行复制到当前行下方
:t6 把当前行复制到第六行下方
:t. 为当前行创建一个副本(类似与普通模式下的yyp)
:t$ 把当前行复制到文本结尾
:’<,’>t0 把高亮选中的行复制到文件开头
用:m 命令移动行
我们可以把它简写为一个字母:m
再选中高亮选区后,只需要简单的执行命令:’<,’>m$,就可以把当前选中的行移动到文件末尾. 和dGp效果一样.
重复上次的Ex命令很简单,只需要按@:即可.
技巧30 在指定范围上执行普通模式命令
如果想在一系列连续行上执行一条普通模式命令,我们可以用:normal命令,此命令在与.命令或者宏结合使用时,我们只需花费很少的努力就能完成大量复杂重复性的任务.
:’<,’>normal . 命令可以解读为”对高亮选区中的每一行,对其执行普通模式下的.命令”,无论是操作5行还是50行文本,这种方法都能出色地完成任务,更棒的是我们甚至不需要计算行数,在可视模式中选中这些行使我们拜托了计数的负担.
这个例子使用:normal执行.命令,但是也可以用这种方式执行其他的普通模式命令,例如,可以用如下命令解决上面的问题:
%normal A;
符号% 代表了整个文件范围,因此:%normal A; 告诉vim在文件每行的结尾都要添加一个分号,在做此修改时会切换到插入模式,但是修改完成之后vim会自动返回到普通模式.
:%normal i//
:%normal @q应对较为复杂的任务
本文介绍如何在Vim编辑器中高效地对代码进行修改和管理,包括在不同长度的高亮块后添加文本、利用可视模式操作非方形文本区域、在命令行模式下执行批量替换等实用技巧。
375

被折叠的 条评论
为什么被折叠?



