Vim宏在视觉选择的每一行


85

我想在选择中的每一行上运行一个宏,而不是总计总的行数。例如,我可以编写一个宏进行转换:

Last, First

进入

First Last

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

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

对Vim大师有什么想法吗?

编辑:这仅是一个例子,显然这很容易被修改,但是还有其他实例并不太容易,我更喜欢使用宏。


1
老实说,我可能会使用正则表达式来完成此特定任务。但是这个问题在更复杂的情况下仍然有效。
Jamie Wong

为什么是vim?我认为sed更合适。
kokosing

8
@kogut:为什么退出编辑器以使用一行正则表达式编辑文本?
斯蒂芬

1
好的,您已经明白了;)
kokosing 2010年

Answers:


152

假设您有一个q在同一行上运行(并保留)的宏。然后,您可以使用以下命令在选择的每一行上运行它:

:'<,'>normal @q

(如果您已经选择了一组行,则在命令行上单击:产生:'<,'>

例如,以下宏将行中除第一个单词外的所有单词大写:

: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.

6
:let @q="^wgU$"

1
@rampion:您的命令中有错字吗?对我来说,它只能像这样工作::'<,'>normal! @q
奥利弗·奥利弗

3
@oliver:检查您的映射-您可能已重新映射@q。来自:help normal-“如果给出[!],将不使用映射。”

2
@rampion:该死的...你是对的!我使用yankring,显然存在问题:...您无法使用“:normal @a”执行宏。仍然不可能,但是您可以使用“:normal!@a”(来自yankring的帮助文档)执行它
Oliver

1
我个人喜欢这样@在可视模式下进行映射:vnoremap @ :normal @。这样,您仍然可以按照@a您的期望进行操作(尽管之后必须按Enter :()
LondonRob

19

选择行,然后按:进入命令模式。Vim将自动填充'<,'>,这会将范围限制为选定的行。对于您的示例,您可以使用以下:s命令进行交换:

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

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

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

如果要在每一行上重播已录制的宏,则需要使用: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

这比接受的答案更好,因为它支持添加新行的宏。
JanWarchoł17年

@ Dave,Kirby也许最好^.它进行交换,以使宏仅在具有某些文本的行上运行,不是吗?
SergioAraujo

1

您可以将以下功能添加到您的功能中,也可以将其~/.vimrc复制到浏览器中并运行:@+

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

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

:Rover a
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.