vim range .+1,$包括当前行,影响一行太多
vim range .+1,$ includes current line, affecting one line too much
我有一个 vim 脚本来帮助 Python 代码重构;根据文件的不同,它会插入多个相等的 import
行,例如如果许多行更改为使用 getToolByName
.
,则会出现多次 from Products.CMFCore.utils import getToolByName
为了清理,我在脚本末尾添加了如下几行:
normal gg
/^\(from AccessControl import Unauthorized\>\)\?/
.+1,$s,^from AccessControl import Unauthorized\n,,e
normal gg
/^\(from Products.CMFCore.utils import getToolByName\>\)\?/
.+1,$s,^from Products.CMFCore.utils import getToolByName\n,,e
想法是:
- 对于每个可能插入的导入行,
- 转到文件顶部,
- 寻找包含此导入的第一行(好吧,从它开始,可能包含更多),
- 并删除所有进一步行(
.+1,$
)完全插入的导入。
为了避免错误(这会 造成很大伤害,尤其是在通过 :argdo
使用脚本时),我将搜索设为可选 (\?
) ,因为 e
标志仅适用于 :s
命令。如果该搜索未找到真正的匹配项,则以下 :.+1,$ s
命令也不应删除任何内容,因为它更具限制性。
(剩余的插入行需要手动移动)
但是,由于 \?
,替换不仅删除了以下出现的事件 (.+1
),而且删除了 所有 - 包括我第一次出现的想留着。
我该如何解决这个问题?
基于 sed
的解决方案也会对我有所帮助。
版本:
vim v7.4 (CentOS Linux) 和 Windows.
上的 gvim 8.1 同样的问题
谢谢!
编辑:
现在我有了一个解决方法,我仍然对不需要临时更改的“适当”解决方案感兴趣,因此 vim
认为文件 未更改 如果一切已经很好了
这可能不是最佳解决方案,但这是我找到的解决方法:
在第一行 normal gg
上面,我添加了代码以在文件末尾添加两行:
normal GoELEPHANT IN CAIRO
normal yyp
然后我将 /.../
行更改为 无条件地 但 或者 找到那些额外的行,例如:
normal gg
/^\(from AccessControl import Unauthorized\>\|ELEPHANT IN CAIRO\)/
.+1;$ s/^from AccessControl import Unauthorized\n//e
最后我删除了那些行:
g/^ELEPHANT IN CAIRO$/d
如您所见,问题的发生是因为您搜索 from AccessControl import Unauthorized
时使用的是 ?
,这实际上使它匹配 每 行,并且不是实际导入的第一行。
您可以通过使用与您想要匹配的确切行相匹配的模式来解决此问题,但使用 :silent!
来防止任何错误破坏您的序列。
这可行:
normal gg
silent! /^from AccessControl import Unauthorized\>/
.+1,$s,^from AccessControl import Unauthorized\n,,e
但更好的解决方案是使用一个范围来查找模式并同时从下一行开始。您还可以使用 :d
命令删除一行,并使用 :g//d
删除与特定正则表达式匹配的所有行(范围内)。此外,如果您两次使用相同的模式,那么在 :g
命令上简单地使用 //
将再次匹配相同的模式。
综合起来:
:0/^from AccessControl import Unauthorized\>/+1,$g//d
所以这从第 0 行开始(在文件开头之前,所以它也在文件的第一行匹配),然后找到第一次出现的模式,然后从后面的行开始, 一直到文件末尾查找相同模式的所有其他匹配项,并删除匹配的行。
与之前相同,如果您不想在模式不匹配时看到错误(或者如果只有一个匹配,在这种情况下 :g//
将失败),您可以使用:silent!
再次压制它。
:silent! 0/^from AccessControl import Unauthorized\>/+1,$g//d
我有一个 vim 脚本来帮助 Python 代码重构;根据文件的不同,它会插入多个相等的 import
行,例如如果许多行更改为使用 getToolByName
.
from Products.CMFCore.utils import getToolByName
为了清理,我在脚本末尾添加了如下几行:
normal gg
/^\(from AccessControl import Unauthorized\>\)\?/
.+1,$s,^from AccessControl import Unauthorized\n,,e
normal gg
/^\(from Products.CMFCore.utils import getToolByName\>\)\?/
.+1,$s,^from Products.CMFCore.utils import getToolByName\n,,e
想法是:
- 对于每个可能插入的导入行,
- 转到文件顶部,
- 寻找包含此导入的第一行(好吧,从它开始,可能包含更多),
- 并删除所有进一步行(
.+1,$
)完全插入的导入。
为了避免错误(这会 造成很大伤害,尤其是在通过 :argdo
使用脚本时),我将搜索设为可选 (\?
) ,因为 e
标志仅适用于 :s
命令。如果该搜索未找到真正的匹配项,则以下 :.+1,$ s
命令也不应删除任何内容,因为它更具限制性。
(剩余的插入行需要手动移动)
但是,由于 \?
,替换不仅删除了以下出现的事件 (.+1
),而且删除了 所有 - 包括我第一次出现的想留着。
我该如何解决这个问题?
基于 sed
的解决方案也会对我有所帮助。
版本: vim v7.4 (CentOS Linux) 和 Windows.
上的 gvim 8.1 同样的问题谢谢!
编辑:
现在我有了一个解决方法,我仍然对不需要临时更改的“适当”解决方案感兴趣,因此 vim
认为文件 未更改 如果一切已经很好了
这可能不是最佳解决方案,但这是我找到的解决方法:
在第一行 normal gg
上面,我添加了代码以在文件末尾添加两行:
normal GoELEPHANT IN CAIRO
normal yyp
然后我将 /.../
行更改为 无条件地 但 或者 找到那些额外的行,例如:
normal gg
/^\(from AccessControl import Unauthorized\>\|ELEPHANT IN CAIRO\)/
.+1;$ s/^from AccessControl import Unauthorized\n//e
最后我删除了那些行:
g/^ELEPHANT IN CAIRO$/d
如您所见,问题的发生是因为您搜索 from AccessControl import Unauthorized
时使用的是 ?
,这实际上使它匹配 每 行,并且不是实际导入的第一行。
您可以通过使用与您想要匹配的确切行相匹配的模式来解决此问题,但使用 :silent!
来防止任何错误破坏您的序列。
这可行:
normal gg
silent! /^from AccessControl import Unauthorized\>/
.+1,$s,^from AccessControl import Unauthorized\n,,e
但更好的解决方案是使用一个范围来查找模式并同时从下一行开始。您还可以使用 :d
命令删除一行,并使用 :g//d
删除与特定正则表达式匹配的所有行(范围内)。此外,如果您两次使用相同的模式,那么在 :g
命令上简单地使用 //
将再次匹配相同的模式。
综合起来:
:0/^from AccessControl import Unauthorized\>/+1,$g//d
所以这从第 0 行开始(在文件开头之前,所以它也在文件的第一行匹配),然后找到第一次出现的模式,然后从后面的行开始, 一直到文件末尾查找相同模式的所有其他匹配项,并删除匹配的行。
与之前相同,如果您不想在模式不匹配时看到错误(或者如果只有一个匹配,在这种情况下 :g//
将失败),您可以使用:silent!
再次压制它。
:silent! 0/^from AccessControl import Unauthorized\>/+1,$g//d