【问题标题】:Duplicating line in Vim and appending few letters在 Vim 中复制行并附加几个字母
【发布时间】:2013-03-11 12:26:01
【问题描述】:

我正在编辑文本文件中的字典,其中包含俄语单词 - 每行一个单词。

一些名词缺少派生词,通常是同一个词加上几个字母 - 有 6-7 种变体,如下图所示:

在 Vim 中,我想将光标放在第一列并逐行向下滚动。当我识别一个名词时,我想按一些(尽可能少!)击键来获取该单词,将其复制到单独的行中并附加字母。

我可以稍后通过发出%sort u 来消除重复项。

如果我可以在整个文件上运行该命令,它将类似于:

%s/\(.\+\)$/\1^M\1а^M\1ам^M\1ами^M\1ах^M\1е^M\1ном^M/

您有什么想法,如何在 Vim 中创建这样的“宏”?

【问题讨论】:

    标签: vim macros text-editor vi


    【解决方案1】:

    有几种方法可以解决这个问题。您可以创建宏,也可以创建地图。两者都可以在运行 VIM 时完成。两者都可以放在另一个文件中(例如,您的.vimrc,或具有特定于该项目的绑定的文件)并在需要时获取。

    我也会给你更多关于正则表达式的建议:如果你写的东西特别复杂,你可以通过以\v开头的正则表达式来大大减少\s的数量(即@987654324 @)。

    在 VIM 中创建宏

    您可以通过在普通模式下按 q 来在 VIM 中启动宏,然后按您希望用于宏的键。然后,您可以通过按 @ 后跟宏的字母来调用宏。在普通模式下再次按 q 停止录制。

    因此,您可以按如下方式输入此宏(使用q 寄存器):

    qq:s/\(.\+\)$/\1\r\1а\r\1ам\r\1ами\r\1ах\r\1е\r\1ном\r/回车q

    然后,当你在一行并且想要运行这个命令时,从普通模式输入 @q

    将宏存储在文件中并获取它

    当您在最后一步创建宏时,您实际所做的是设置q 寄存器。您可以通过在命令模式下输入registers 来检查这一点。你可以改为在.vimrc 文件中设置这个宏,如下所示,每次启动 VIM 时它都可用。

    1. 创建您要在其中存储此宏的文件 (:new)。
    2. 将以下行添加到文件中:

      let @q=":s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"

      (如果你用 Ctrl+R" 拉出该行并将其粘贴到 VIM 中,则该行末尾将有一个正确的 ^M 字符。您需要进行一些手动编辑以确保它在引号内。或者,您可以输入 Ctrl+VCtrl+M 以输入 ^M 字符。 )

    3. 保存文件 (:w testmacro.vim)。
    4. 来源它(:so %:source %)。
    5. 通过在您想要执行此操作的行之一上键入 @q 来测试您的宏。

    稍后,您将能够通过运行 :so testmacro.vim 来加载此宏。

    创建映射

    您可以改为创建映射。以下映射复制给定行中的最后一个单词,将其粘贴到以下六行,然后附加到给定的每一行。

    nnoremap <c-j> yy6pAа<esc>jAам<esc>jAами<esc>jAах<esc>jAе<esc>jAном<esc>j

    “nnoremap”开头的n表示它只在正常模式下起作用。
    noremap表示该命令不会进行任何递归重映射(而nmap可能会发生这种情况)。 <c-j> 映射到 Ctrl+J yy6p 拉出该行并粘贴 6 次。 Aa<esc>j 追加到当前行的末尾,输入文本(在本例中为 a),退出插入模式,并下移一行。

    你可以在vim的命令模式下输入这个命令,也可以把它存到一个文件中,用:source命令加载。

    将寄存器与映射相结合

    您可以访问映射中的寄存器。这意味着,如果您知道输入给定的替换正则表达式会执行您想要的操作,您可以将其保存在寄存器中,然后在当前行输入您的命令。

    为此,请在文件中输入以下命令,然后获取它:

    nnoremap <c-i> :<c-r>f<cr>
    let @f="s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"
    

    现在您可以输入 Ctrl+I 在当前行的寄存器 f 中运行替换正则表达式。

    或者,将一些寄存器专用于该目的 - 比如说 a-f。

    nnoremap <c-l> yy6p$"apj"bpj"cpj"dpj"epj"fpj
    let @a="a"
    let @b="ам"
    let @c="ами"
    let @d="ax"
    let @e="e"
    let @f="ном
    

    在这种情况下,我们使用了在点击使用它的命令(例如粘贴)之前按 " 和寄存器名称的功能。

    【讨论】:

    • 我看不到最初的qqq 的意义。最终的q 会将q 寄存器设置为适当的值,而不管开始时寄存器中的内容是什么。
    • @ChrisMorgan,你是对的。我有一些关于创建递归宏的建议。
    【解决方案2】:

    您可以在escape 模式下按q 录制宏。例如,

    1. 将光标放在要编辑的名词上。
    2. qa开始录制宏并将其存储在寄存器a中(其他字母和数字也可用于寄存器)。
    3. 执行您想要执行的任何常规操作(复制行、粘贴、附加字母等,就像您尝试在搜索字符串中显示的那样)。
    4. 完成更改后,在escape 模式下再次按q

    您的宏现在在寄存器a 中创建。每当您想重复按键序列时,只需按@a

    请注意,您可以在recording 模式下执行任何操作,包括任何类型的命令、插入、光标移动等。有关宏和相关选项的更多信息,请查看 Vim 帮助:h complex-repeat

    Vim 寄存器被共享为宏和 yanked 测试的占位符;此功能甚至允许您在文件中保存和编辑宏。详情请见this question

    【讨论】:

      【解决方案3】:

      这是一个地图解决方案 - 将行复制到缓冲区中,然后使用 p 粘贴。 A 附加在行尾

        map <F2> 0dwpo<esc>pAa<enter><esc>pAam<enter><esc>pAax ...etc
      

      【讨论】:

      • 我打算提出类似的建议,但是将所有 8 个都拉出然后粘贴,然后进行附加:map t yy8pAa^[jAaM^[jAaMN...(您可以通过键入 control-v 然后 control-[ 来逃避)
      【解决方案4】:

      如果你的目标是,当你的光标在一个特殊的词上,然后按下一些东西,vim 会附加不同的“后缀”(我希望我用了正确的词,但你知道我的意思)。您可以使用宏 (q)。但是,由于您已经编写了 :s 命令,因此您可以使用该命令创建一个映射,执行相同的操作,并且会更短。

      在命令行中,您可以通过按&lt;c-r&gt;&lt;c-w&gt; 来获取光标下的单词。所以你可以试试:

      nnoremap <leader>z :s/<c-r><c-w>/& & &..../<cr>
      

      我没有写 &amp; &amp; &amp;... 部分,因为我不知道(从未尝试过,我在 windows 下没有 vim。我什至没有 windows)如果换行符 \n 可能是windows下在这里使用。 &amp; 表示整个匹配的部分,在这种情况下是您光标下的单词。

      所以你只需将光标移动到单词上,输入&lt;leader&gt;z,vim 就会为你完成这项工作。 (如果更换部件是正确的:))。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-09
        • 1970-01-01
        • 2019-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-29
        • 2012-02-20
        相关资源
        最近更新 更多