关于Vim:你对Vim最有效的捷径是什么?

What is your most productive shortcut with Vim?

我听说过很多关于Vim的事,包括利弊。实际上,作为一个开发人员,使用VIM应该比使用任何其他编辑器都快。我用VIM做一些基本的工作,我用VIM的效率最多降低10倍。

当你谈论速度时,你应该关心的只有两件事(你可能对速度不够关心,但你应该关心):

  • 左右交替使用手是使用键盘。
  • 永远不要触摸鼠标第二种方法是尽可能快。你移动你的手需要很长时间,抓住鼠标,移动它,然后拿过来回到键盘上看看键盘确定你把你的手放回正确的地方)
  • 下面有两个例子说明了为什么我对VIM的工作效率要低得多。

    复制/剪切和粘贴。我总是这么做。对于所有当代的编辑器,您可以用左手按shift,然后用右手移动光标以选择文本。然后复制ctrl+c,移动光标并粘贴ctrl+v

    对维姆来说,这很可怕:

    • yy复制一行(几乎不需要整行!)
    • [number xx]yyxx行复制到缓冲区中。但你永远不知道你是否选择了你想要的。我经常要先做[number xx]dd,然后再做u,才能撤销!

    另一个例子?搜索和替换。

    • 在pspad:ctrl+f中,键入要搜索的内容,然后按enter
    • 在vim:/中,键入要搜索的内容,然后如果有一些特殊字符将\放在每个特殊字符之前,则按enter

    维姆的一切都是这样的:似乎我不知道如何正确地处理它。

    注意:我已经读过VIM备忘表了。)

    我的问题是:

    你使用VIM的方式是什么,使你比当代编辑更有效率?


    你对维姆的问题是你不摸摸维伊。

    你提到用yy切割,抱怨你几乎不想切割整条线。实际上,程序员在编辑源代码时,常常希望处理整行、行范围和代码块。然而,yy只是将文本拉入匿名复制缓冲区(或在vi中称为"寄存器")的众多方法之一。好的。

    vi的"禅"就是你说的是一种语言。开头的y是一个动词。声明yyy_的同义词。由于y是一种非常常见的操作,因此它被加倍以便于输入。好的。

    这也可以表示为ddP(删除当前行并将副本粘贴回原处;将副本保留在匿名寄存器中作为副作用)。yd动词的"主语"是任何动作,因此yW是"从这里(光标)到当前/下一个(大)词的结尾",y'a是"从这里向含有‘A’标记的行"的扬克"。好的。

    如果您只了解基本的上、下、左、右光标移动,那么vi将不会比您的"记事本"副本更有效率。(好的,您仍然可以突出显示语法,并且能够处理大于大约45kb的文件;但是请在这里与我一起工作)。好的。

    vi有26个"标记"和26个"寄存器"。使用m命令将标记设置到任何光标位置。每个标记都由一个小写字母指定。因此,ma将"A"标记设置为当前位置,mz将"Z"标记设置为当前位置。您可以使用'命令(单引号)移动到包含标记的行。因此,'a移动到包含"A"标记的行的开头。您可以使用`命令(backquote)移动到任何标记的精确位置。因此,`z将直接移动到"Z"标记的确切位置。好的。

    因为这些是"运动",它们也可以用作其他"陈述"的主题。好的。

    因此,剪切任意文本选择的一种方法是删除一个标记(我通常使用"a"作为"第一"标记,使用"z"作为下一个标记,使用"b"作为另一个标记,使用"e"作为另一个标记(我不记得在使用vi的15年中交互使用了超过四个标记;一种方法创建了自己关于mac如何使用标记和寄存器的约定不会干扰人的互动环境的ROS)。然后我们转到所需文本的另一端;我们可以从任意一端开始,这无关紧要。然后我们可以简单地使用d`a进行剪切,或者使用y`a进行复制。因此,整个过程有5个击键开销(如果我们以"插入"模式开始,并且需要esc-out命令模式,则为6个)。一旦我们剪切或复制了,粘贴到一个副本中就是一次按键:P。好的。

    我说这是剪切或复制文本的一种方法。然而,它只是众多中的一个。通常,我们可以更简洁地描述文本的范围,而无需移动光标和删除标记。例如,如果我在一段文字中,我可以分别使用{}移动到该段的开头或结尾。所以,为了移动一段文本,我使用{d}键来剪切它。(如果我恰好在段落的第一行或最后一行,那么我可以分别使用d}d{。好的。

    "段落"的概念默认为通常凭直觉是合理的。因此,它常常适用于代码和散文。好的。

    我们经常知道一些模式(正则表达式),它标志着我们感兴趣的文本的一端或另一端。向前或向后搜索是vi中的运动,因此在我们的"语句"中它们也可以用作"主语"。因此,我可以使用d/foo从当前行剪切到包含字符串"foo"的下一行,使用y?bar从当前行复制到包含"bar"的最新(上一行)。如果我不希望整行仍然可以使用搜索动作(作为自己的语句),删除我的标记并使用前面描述的`x命令。好的。

    除了"动词"和"主语"之外,vi还有"宾语"(在这个术语的语法意义上)。到目前为止,我只描述了匿名寄存器的使用。但是,我可以通过在"object"引用前面加上"(双引号修饰符)来使用26个"命名"寄存器中的任何一个。因此,如果我使用"add,我将当前行剪切到"A"寄存器,如果我使用"by/foo,那么我将文本的副本从这里拉到包含"foo"的下一行,拉到"B"寄存器。要从寄存器粘贴,我只需在粘贴前加上相同的修改序列:"ap将"A"寄存器内容的副本粘贴到光标后的文本中,"bP将副本从"B"粘贴到当前行之前。好的。

    "前缀"这一概念也为我们的文本操作"语言"添加了语法"形容词"和"副词"的类似词。大多数命令(动词)和动作(动词或对象,取决于上下文)也可以使用数字前缀。因此,3J的意思是"连接下三行",d5}的意思是"从当前行到第五段末尾从这里删除"。好的。

    这都是中级六级。没有一个是特定于vim的,而且如果你准备好学习的话,在vi中还有很多高级技巧。如果你仅仅掌握了这些中间概念,那么你可能会发现你很少需要编写任何宏,因为文本操作语言足够简洁和表达,可以使用编辑器的"本机"语言轻松地完成大多数事情。好的。更高级技巧的示例:

    有许多:命令,最显著的是:% s/foo/bar/g全局替换技术。(这不是高级命令,但其他:命令可以)。整个:命令集在历史上都是由vi以前的ed(行编辑器)和ex(扩展行编辑器)实用程序继承的。事实上,vi之所以如此命名是因为它是ex的可视接口。好的。

    :命令通常在文本行上运行。ED和EX是在终端屏幕不常见,许多终端都是"电传打字机"(TTY)设备的时代编写的。因此,通过一个非常简洁的界面使用命令从文本的打印副本开始工作是很常见的(常见的连接速度是110波特,大约是每秒11个字符——比快速打字员慢;在多用户交互会话中,LAG很常见;此外,通常还有一些节省纸张的动机)。好的。

    因此,大多数:命令的语法包括一个地址或地址范围(行号),后跟一个命令。很自然地,人们可以使用文字行号::127,215 s/foo/bar将127到215之间每行的第一个"foo"变为"bar"。也可以对当前行和最后一行分别使用一些缩写,如.$。也可以使用相对前缀+-分别表示当前行之后或之前的偏移量。由此可见::.,$j的意思是"从当前行到最后一行,把它们连接成一行"。:%:1,$同义(所有行)。好的。

    :... g:... v命令有一些解释,因为它们非常强大。:... g是"global"的前缀,对所有与模式匹配的行(正则表达式)应用后续命令,而:... v对所有与给定模式不匹配的行("v"from"converse")应用此命令。与其他ex命令一样,这些命令可以通过寻址/范围引用作为前缀。因此,:.,+21g/foo/d的意思是"从当前行到下21行删除包含字符串"foo"的任何行",而:.,$v/bar/d的意思是"从这里到文件末尾,删除不包含字符串"bar"的任何行。"好的。

    有趣的是,普通的unix命令grep实际上是受到这个ex命令的启发(并以文档中的方式命名)。ex命令EDOCX1(grep)是他们记录如何"全局"打印包含"正则表达式"(re)的行的方式。当使用ed和ex时,:p命令是所有人最先学习的命令之一,并且通常是编辑任何文件时使用的第一个命令。这就是您如何打印当前内容(通常一次只打印一页,使用:.,+25p或其他类似内容)。好的。

    请注意,:% g/.../d或(其反向/反向对应物::% v/.../d是最常见的使用模式。但是,还有几个其他的ex命令值得记住:好的。

    我们可以用m来移动线条,用j来连接线条。例如,如果您有一个列表,并且您希望在不删除它们的情况下分离所有匹配的内容(或者相反地不匹配某些模式),那么您可以使用诸如::% g/foo/m$……所有的"foo"行将被移动到文件的末尾。(注意另一个关于使用文件结尾作为草稿空间的提示)。这将保留所有"foo"行的相对顺序,同时从列表的其余部分提取它们。(这相当于做一些类似于:1G!GGmap!Ggrep foo1G:1,'a g/foo'/d(将文件复制到自己的尾部,通过grep过滤尾部,并从头部删除所有内容)。好的。

    为了连接线条,通常我可以找到所有需要连接到其前一行的线条的模式(例如,在某些项目符号列表中,所有以"^"开头而不是"^*"开头的线条)。对于这种情况,我将使用::% g/^ /-1j(对于每个匹配行,向上一行并连接它们)。(顺便说一句:对于试图搜索项目符号行并连接到下一行的项目符号列表,由于以下几个原因,不起作用…它可以将一个项目符号行连接到另一个项目符号行,并且不会将任何项目符号行连接到它的所有延续;它只在匹配项上成对工作)。好的。

    几乎不用说,您可以使用我们的老朋友sgv命令(global/converse global)。通常你不需要这样做。但是,考虑一些情况,您只想在与其他模式匹配的行上执行替换。通常,您可以使用带有捕获的复杂模式,并使用返回引用来保留不希望更改的部分行。然而,将匹配与替换分开通常会更容易::% g/foo/s/bar/zzz/g--对于包含"foo"的每一行,用"zzz"替换所有的"bar"。(类似于:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g--只适用于"bar"前面是同一行"foo"的情况;这已经不够笨拙了,必须是人。进一步了解"bar"在"foo"之前的所有情况)好的。

    问题是,在ex命令集中,不只是psd行。好的。

    :地址也可指标记。因此,如果字符串foo位于"a"和"b"标记之间,则可以使用::'a,'bg/foo/j将任何包含字符串foo的行连接到其后续行。(是的,所有前面的ex命令示例都可以通过在这些寻址表达式之前加前缀的方式限制在文件行的子集中)。好的。

    这很难理解(在过去的15年里我只使用过几次类似的东西)。不过,我可以自由地承认,我经常重复和互动地做一些事情,如果我花时间思考正确的咒语,可能会更有效地完成这些事情。好的。

    另一个非常有用的vi或ex命令是:r,用于读取另一个文件的内容。因此::r foo在当前行插入名为"foo"的文件的内容。好的。

    更强大的是:r!命令。这将读取命令的结果。这与挂起vi会话、运行命令、将输出重定向到临时文件、恢复vi会话以及从temp中读取内容相同。文件。好的。

    更强大的是!:... !命令。它们还执行外部命令并将结果读取到当前文本中。但是,它们还通过命令过滤文本的选择!这样,我们可以使用1G!Gsort对文件中的所有行进行排序(G是vi"goto"命令;它默认转到文件的最后一行,但可以加上行号前缀,例如1,第一行)。这相当于前变体:1,$!sort。作者通常将!与unix fmt或fold实用程序一起使用,以重新格式化或"换行"文本选择。一个非常常见的宏是{!}fmt(重新格式化当前段落)。程序员有时使用它通过缩进或其他代码重新格式化工具来运行他们的代码,或者只是部分代码。好的。

    使用:r!!命令意味着任何外部实用程序或过滤器都可以作为编辑器的扩展。我偶尔会将这些脚本用于从数据库中提取数据的脚本,或者用于从网站中提取数据的wget或lynx命令,或者用于从远程系统中提取数据的ssh命令。好的。

    另一个有用的ex命令是:so(:source的缩写)。这将以一系列命令的形式读取文件的内容。当您正常地启动vi时,它隐式地在~/.exinitrc文件上执行:source(vim通常在~/.vimrc文件上执行此操作,这很自然)。它的用途是,您可以通过简单地在一组新的宏、缩写和编辑器设置中寻源来动态更改编辑器配置文件。如果你偷偷摸摸的话,你甚至可以用它来存储一系列的前编辑命令,以便按需应用到文件中。好的。

    例如,我有一个七行文件(36个字符),它通过wc运行一个文件,并在包含该字数数据的文件顶部插入一个C样式的注释。我可以使用如下命令将该"宏"应用于文件:vim +'so mymacro.ex' ./mytarget。好的。

    (vi和vim的+命令行选项通常用于在给定的行号处启动编辑会话。然而,很少有人知道,可以通过任何有效的ex命令/表达式(如我在这里所做的"source"命令)跟踪+;对于一个简单的示例,我有一些脚本调用:vi +'/foo/d|wq!' ~/.ssh/known_hosts在我对一组服务器进行映像时,以非交互方式从我的ssh已知主机文件中删除一个条目。好的。

    通常,使用perl、awk、s ed(实际上,就像grep一样,grep是一个受ed命令启发的实用程序)编写这样的"宏"要容易得多。好的。

    @命令可能是最模糊的vi命令。在近十年的高级系统管理课程教学中,我偶尔会遇到很少有人使用过它。@执行寄存器的内容,就好像它是vi或ex命令一样。示例:我经常使用::r!locate ...在我的系统中查找一些文件,并将其名称读取到我的文档中。从那里我删除了所有无关的点击,只留下我感兴趣的文件的完整路径。我只是使用以下方法,而不是费力地通过路径的每个组件(或者更糟的是,如果我碰巧卡在一台机器上,而在其vi副本中不支持制表符完成:好的。

  • 0i:r(将当前行转换为有效的:r命令)
  • "cdd(删除"c"寄存器中的行)和
  • @c执行该命令。
  • 这只需要10次击键(对于我来说,表达式"cdd@c实际上是一个手指宏,所以我几乎可以像任何常见的六个字母单词一样快速地输入它)。好的。清醒的想法

    我只触及了vi的力量的表面,这里我所描述的甚至都不是vim命名的"改进"的一部分!我在这里描述的所有内容都应该适用于20或30年前的任何旧版本的vi。好的。

    有些人使用了比我任何时候都要多的vi的力量。好的。好啊。


    你说的是文本的选择和复制,我认为你应该看看VIM的视觉模式。

    在可视模式下,您可以使用VIM命令选择文本,然后您可以对所选内容进行任何操作。

    考虑以下常见情况:

    您需要选择到下一个匹配的括号。

    你可以这样做:

    • 如果光标在开始/结束括号上,则返回v%
    • 如果光标在括号内,则返回vib

    要在引号之间选择文本:

    • 六"双引号
    • 单引号

    您要选择一个大括号块(在C样式语言中非常常见):

    • vib
    • vi{

    要选择整个文件:

    • ggVG

    可视块选择是另一个非常有用的功能,它允许你选择一个矩形的文本区域,你只需要按ctrl vbkbd启动它,然后选择你想要的文本块,执行任何类型的操作,如扬克、删除、粘贴、编辑等等。编辑面向列的文本是很好的。