我已经在带有和不带有〜/ .vimrc的Vim 8.1和Neovim(nvr 2.1.10)中进行了尝试(后者用于检查vimrc条目是否具有因果关系-无效)。
给出这个例子
apple
banana
carrot
dates
我可以记录一个宏(@a)
yy
p
拉动并粘贴(即复制)一行。当我将(@a)该宏应用于单个行,并在单个行中重复该宏(@@)时,它将复制该行。
但是,当我直观地选择这些行并尝试应用宏时,尝试其中的任何一条
:'<,>'norm @a ## :'<,>'norm @a on single line works
:'<,>'normal @a
:'<,>'norm! @a
:'<,>':norm @a
:'<,>':normal @a
:'<,>':norm! @a
:1,4norm! @a ## https://stackoverflow.com/a/390194/1904943
等宏在所选文本中的第一行中重复(每行一次):
apple
apple
apple
apple
apple
banana
carrot
dates
这是什么问题?
答案 0 :(得分:2)
您看到此问题的原因是因为范围在ex命令上的工作方式。
指定范围时,在进行任何操作之前,该范围将被评估为行号。在这种情况下,'<
的计算结果为1,而'>
的计算结果为4,因为它们是线性操作。当您第一次在第1行运行宏时,将使用“ apple”创建新行。当宏在第2行上运行时,该行包含“ apple”,因此该单词被复制,依此类推。使用该命令执行时该行上的内容。如果您使用%
(针对所有行)或2,4
选择“香蕉”及以下内容,则会看到相同的行为。
但是,POSIX为:g
命令指定了不同的行为:
global和v命令在逻辑上是两次通过操作。首先,在指定行中标记除终止符以外的行匹配(全局)或不匹配(v或全局!)指定模式的行。其次,执行命令给定的ex命令,并将当前行('。')设置为每个标记行。
这就是:g/^/norm yyp
在这里工作的原因:因为要修改的行在执行之前就被标记了,只有被标记的行才执行命令。不考虑事实之后插入的行。正如您指出的,:g
确实接受范围,因此您可以将操作限制为要处理的一组行。