正则表达式/ Vim:匹配除模式之外的所有内容,其中模式是多行的?

时间:2012-02-14 16:28:01

标签: regex vim

Vim是否有办法对

执行类似的操作
:v/PATTERN/d 

其中PATTERN是多行正则表达式?我确信有一种方法可以在脚本中执行此操作,但我很好奇是否可以仅使用标准正则表达式替换或Vim命令,因为此时它比实际需要更具学术性。 / p>

我的例子如下:

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模式不匹配的字符串,但我无法掌握如何使用后视或任何东西来实现。正则搜索时正则表达式完全正常,但我无法弄清楚如何告诉正则表达式引擎找到所有内容但该模式。有什么想法吗?

3 个答案:

答案 0 :(得分:8)

clear reg a

qaq

begin...end追加到注册a

:g/begin/,/end/y A

打开新标签

:tabnew

放入reg a

"ap

答案 1 :(得分:2)

将其翻转出去,并删除由模式分隔的所有内容:

:%s/\%(^end\n*\|\%^\)\zs\_.\{-}\ze\%(^begin\|\%$\)//
  • \%( ... ) - 非捕获组
  • ^end\n* - 模式的结束
  • \%^ - 文件的开头
  • \zs - 在要替换的字符串中不包括此前匹配的任何内容
  • \_.\{-} - 非贪婪匹配任何内容(包括换行符)
  • \ze - 请勿在要替换的字符串中包含此后匹配的内容
  • ^begin - 模式的开头
  • \%$ - 模式的结束

答案 2 :(得分:0)

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

然后删除文件开头和结尾留下的残缺:

:1,/^begin/-1 d
:$?^end?+1,$ d

请注意使用$?^end?+1从文件末尾向后搜索以查找以“end”开头的最后一行。

N.B。如果文件以“begin”开头或以“end”结尾,则最后两个将删除太多,因此请在使用之前进行检查。