每一行视觉选择的 Vim 宏

Posted

技术标签:

【中文标题】每一行视觉选择的 Vim 宏【英文标题】:Vim Macro on Every Line of Visual Selection 【发布时间】:2011-03-21 06:10:30 【问题描述】:

我想在选择的每一行上运行一个宏,而不是在我的脑海中计算行数。例如,我可能会编写一个宏来转换:

Last, First

进入

First Last

我希望它在所有这些行上运行:

Stewart, John 
Pumpkin, Freddy
Mai, Stefan
...

Vim 大师有什么想法吗?

编辑:这只是一个示例,显然这可以简单地进行正则表达式,但还有其他实例不太容易,我更喜欢使用宏。

【问题讨论】:

老实说,我可能会用正则表达式来完成这个特殊的任务。但这个问题对于更复杂的情况仍然有效。 为什么是 vim?在我看来 sed 更合适。 @kogut : 为什么要退出编辑器以使用单行正则表达式编辑文本? 好的,你明白了;) 【参考方案1】:

假设您有一个宏q,它在一行上运行(并保持)。然后你可以在你选择的每一行上运行它:

:'<,'>normal @q

(如果您已经选择了一组行,则在命令行中点击: 会生成:'&lt;,'&gt;

例如,以下宏将除第一个单词之外的每个单词都大写:

:let @q="^dwgU$P"

所以在下面运行它(+ 行被选中)

 0000: a long long time ago
 0001: in a galaxy far away
+0002: naboo was under an attack
+0003: and i thought me and qui-gon jinn
+0004: could talk the federation in
 0005: to maybe cutting them a little slack.

使用上面的normal @q 命令,产生:

 0000: a long long time ago
 0001: in a galaxy far away
 0002: naboo WAS UNDER AN ATTACK
 0003: and I THOUGHT ME AND QUI-GON JINN
 0004: could TALK THE FEDERATION IN
 0005: to maybe cutting them a little slack.

【讨论】:

@Roger Pate:好吧,如果你想打高尔夫球的话:) @rampion:你的命令有错字吗?对我来说,它只能这样工作::'&lt;,'&gt;normal! @q @oliver:检查你的映射——你可能已经重新映射了@q。来自:help normal - “如果给出 [!],则不会使用映射。” @rampion:该死的......你是对的!我使用 yankring,显然这有一个问题:... 你不能用 ":normal @a" 执行宏。这仍然是不可能的,但您可以使用 ":normal!@a" 执行它(来自 yankring 的帮助文档) 我个人喜欢像这样在可视模式下映射@vnoremap @ :normal @。这样你仍然可以像你期望的那样做@a(尽管你必须在之后点击回车:()【参考方案2】:

选择行然后按: 进入命令模式。 Vim 会自动填写'&lt;,'&gt;,它将范围限制在选定的行。对于您的示例,您可以使用 :s 命令进行交换:

:'<,'>s/\(\w\+\), \(\w\+\)/\2, \1/

这将交换视觉选择中每一行上用逗号分隔的两个单词。

您也可以像使用任何其他书签或行位置一样使用'&lt;'&gt;,例如作为移动命令的一部分,因此在正常模式下d'&lt; 将从当前光标位置删除到视觉选择中第一行的开头。即使块不再在视觉上突出显示,标记仍然有效。

如果您想在每一行重播录制的宏,您需要使用:normal 命令执行宏。不幸的是,:normal 命令不能在一系列行上运行,但您可以使用:global 命令修复它。这会在与正则表达式匹配的每一行上运行 :ex 命令,因此您可以这样做:

:'<,'>g/^/ norm @a

解释:

:'<,'>       for every line in the visual block
g/^/         on every line that matches the regex /^/ - i.e. every line
norm         run in normal mode
@a           the macro recorded in a

【讨论】:

这比公认的答案更好,因为它支持添加新行的宏。 @Dave, Kirby 也许将^. 交换会更好,以使宏仅在包含一些文本的行上运行,不是吗?【参考方案3】:

您可以将下面的功能添加到您的~/.vimrc 或简单地将其复制到您的浏览器并运行:@+

fun! RunMacroOverSelection(macroname)
    execute "'<,'>normal @". a:macroname
endfun
com -nargs=1 Rover :call RunMacroOverSelection(<f-args>)
nnoremap <leader>r :Rover<space>

优点是您可以在视觉选择上应用任何宏。 您需要将宏字母作为参数,例如:

:Rover a

【讨论】:

以上是关于每一行视觉选择的 Vim 宏的主要内容,如果未能解决你的问题,请参考以下文章

Vim编辑器的三种模式

Vim:如何将视觉块移动到寄存器?

vim 录制宏,自动循环执行组合操作

vim 录制宏,自动循环执行组合操作

向后搜索视觉模式选择

PrimeReact DataTable:如何(视觉)取消选择行