理解vi
中级应用
你提及使用yy
命令剪切,并抱怨你几乎从来不会剪切整行。事实上程序员在编辑源代码时会经常涉及整行,连续的几行或代码块。yy
只是把文本拷贝到匿名缓冲区(在vi中称为寄存器)的众多方式之一。
“vi”的禅在于你在使用一门语言。首个字母y
是一个动词。语句yy
是y_
的一个同义词。因为它是一个普通字符,重复一个y
使它更容县键入。
与yy
类似的还有dd
p
(删除当前行,把当前行粘贴到某处并拷贝保存在匿名寄存器中)。y
和d
可以把任何可编辑的文本当做操作对象。像yW
操作的是当前光标到下一个词之前的文本。y'a
操作的是当前光标到名为’a’的标记之间的文本。
如果你只会使用上下左右键来移动光标,那么对你来说使用vi在效率上来说并不会比你使用记事本要高(好吧,你还会获得代码高亮和轻松地处理比45KB还大的文本)。
vi有26个标记和26个寄存器。使用m
命令可以在光标所在的任何位置设置一个标记。每个标记使用一个小写的英文字母来表示。像ma
表示在光标所在处设置一个名为’a’的标记。mz
表示在光标所在处设置一个名为’z’的标记。你可以使用单引号'
把光标定位到标记所在的行。如'a
表示把光标移到’a’标记所在的行行首。你还可以使用反引号`来移动光标到标记所在的确切位置。命令z将会移动光标到名为’(反引号)z’(抱歉,反引号+z 不懂怎么在反引号包围中转义)的标记的确切标记处。
上面所说的只是剪切和拷贝的一种方式而已。除了移动光标或使用标记外,我们还可以更简洁地操作。例如在一个文本段中,可以使用{
和}
把光标移到到文本开头处和文本结尾处。如{d}
命令将会剪切整个文本段。d}
命令将会剪切当前光标所在处到文本结尾处之间的文本。d{
命令将会剪切当前光标所在处到文本段开头之间的文本。
通常也会在vi中使用正则表达式。如使用d/foo
命令来剪切当前光标到下一个名为”foo”的字符之间的文本。命令y?bar
将会复制当前光标到前一个名为”bar”的字符之间的文本。
vi中我们还可以使用双引号"
来使用26个寄存器。命令"add
表示把当前行剪切到名为’a’的寄存器中。命令"b/foo
表示把当前光标到下一下”foo”之间的文本复制到名为’b’的寄存器中。"ap
表示把寄存器’a’中的文本粘贴到光标所在行的下一行。"aP
表示把寄存器’a’中的文本粘贴到光标所在行的上一行。
作为一门语言,vi中也可以根据上下文环境使用形容词和副词修饰。如3J
表示合并紧接着的三行。
以上的这些只不过是vi的一些中级应用。还没有涉及到Vim中的特殊用法。如果你打算学习vi的话,里面还是有许多高级特性需要学习的。
一些高级技巧
vi中有许多:
命令。比较著名的有:%s/foo/bar/g
全局替换的使用。一系列的:
命令继承自名为’ed’和’ed’的扩展’ex’编辑器。事实上vi的得名也源于’ex’中的一个命令。
:
系列命令通常作用于多行。ed和ex是上个年代终端显示屏还没流行大部分终端都是”teletype”(TTY)时的产物。因此:
系统命令语法上带有一个作用域(从哪行到哪行)。:127,215
s/foo/bar
表示把在第127行和第215行之间的文本中的”foo”替换为”bar”。也可以使用.
和$
缩写符来表示当前行和尾行。使用+
和-
表示当前行的后间隔和当前行的前间隔。如:.,$j
表示把当前行和尾行之间的所有行合并成一行。:%
命令与:1,$
命令同义。
:... g
和:... v
是极其强大的两个命令。:... g
应用于所有匹配的结果集,:...
v
应用于所有不匹配的结果集。如:.,+21g/foo/d
表示删除当前行和接下来的21行中所有包含”foo”字符的行。:.,$v/bar/d
表示删除当前行和尾行之间所有不包含”bar”字符的行。
有趣的是Unix上grep命令的灵感正是来自ex中的命令。ex中的命令:g/re/p
(grep)表示全局打印符合正则表达式’re’的内容。当使用ed和ex时,:p
是每个人首先要掌握的命令。如:.,+25p
表示打印当前行和接下来的25行。
我们还可以使用m
命令和j
命令来移动行或合并行。如果你想分离出一些匹配或不匹配的行而并不想删除它们。或许你会用到类似:%
g/foo/m$
的命令。它表示把包含有”foo”字符的行移到文件尾部。
需要注意的是你可以使用我们的老朋友s
命令来代替g
和v
命令。一般来说你不必这样做。但是对于一些复杂的匹配操作,你最好还是使用它。比如你想在你匹配出来的结果集中再匹配一些字符并替换它。如:%
g/foo/s/bar/zzz/g
命令表示找出包含”foo”字符的所有行,并在找出来的行中将字符”bar”替换成字符”zzz”。
:
命令中的作用区间也可应用于标记。如:'a,'bg/foo/j
表示合并标记a和标记b之间包含字符”foo”的上下两行。
注:文章大意译自StackOverflow上的一个回答,有删减。
(完)