Vim中是否有方法执行与类似的操作
:v/PATTERN/d
其中PATTERN是多行正则表达式模式?我确信在脚本中有一种方法可以做到这一点,但我主要想知道是否可以只使用标准的regex替换或Vim命令,因为在这一点上,它更具学术性,而不是实际需要。
我的例子如下:
asdf
begin
blah
end
asdf
alsdfjasf
begin
random stuff
end
...
我想得到开始/结束的块,它们之间有线,但忽略块之外的一切,最终以结束
begin
blah
end
begin
random stuff
end
...
我的想法是做
:v/begin_.{-}end/d
如果所有内容都不匹配,则会被删除,甚至复制到寄存器,但显然:v和:g只能在单行上工作。
然后,我开始运行一个替换,并用与begin_.{-}end
模式不匹配的空字符串替换所有内容,但我无法理解如何使用look-behinds或任何东西来实现这一点。正则表达式在搜索时工作得很好,但我不知道如何告诉正则表达式引擎找到除该模式之外的所有内容。有什么想法吗?
清除reg a
qaq
将begin...end
附加到reg a
:g/begin/,/end/y A
打开新选项卡
:tabnew
放入reg a
"ap
将其从内向外翻转,并删除由以下模式分隔的所有内容:
:%s/%(^endn*|%^)zs_.{-}ze%(^begin|%$)//
%( ... )
-非捕获组^endn*
-你的模式结束%^
-文件的开头zs
-在要替换的字符串中不包括在此点之前匹配的任何内容_.{-}
-任何东西的非贪婪匹配(包括换行符)ze
-不要在要替换的字符串中包含任何在此点之后匹配的内容^begin
-你模式的开始%$
-你的模式结束
g和v执行的命令本身可以具有范围,因此您可以使用:g /begin/ .,/end/xxx
对从"开始"到"结束"的所有内容执行操作,其中xxx是要在该范围上执行的命令。你真的不能把它用于:v
,但有几种方法可以在多次通过中做到这一点,例如
"mark all the lines we want to keep by putting '@' at the start of the line"
:g/^begin/ .,/^end/ s/^/@/
"delete all unmarked lines"
:v/^@/ d
"remove the markers"
:s/^@//
当然,这是假设文件中没有任何以@开头的行。
或者,您可以删除每个"结束"和下一个"开始"之间的所有内容
:g/^end/ +1,/^begin/-1 d
然后删除留在文件开头和结尾的cruft:
:1,/^begin/-1 d
:$?^end?+1,$ d
注意使用$?^end?+1
从文件末尾向后搜索,以找到以"end"开头的最后一行。
注意:如果文件以"begin"开头或以"end"结尾,那么最后两个会删除太多内容,所以在使用它们之前请检查。