Visual Studio中的多行正则表达式

106

是否有办法让Visual Studio跨越多行执行正则表达式替换(允许匹配跨越行边界)?我知道有很多编辑器可以做到这一点,但是似乎很奇怪这个功能被遗漏在Visual Studio中。我是不是漏了什么?

7个回答

90

谢谢,这个完美地运行了,</label>.*\r?\n.*<div 中的 \r?\n 是明显的回车换行符,而 .* 则用于匹配可能的制表符/空格。 - Sam
我收到了错误信息:“当前不支持文字'\n'”。 - ELI7VH
@ELI7VH,我无法重现你的错误,请问你使用的是哪个版本的Visual Studio? - Giles Roberts

37

使用 (.*\n)*? 来跳过表达式之间的零个或多个行。

start(.*\n)*?end

找到

start
two
three
end

?是非贪婪操作符,用于尽可能少地跳过几行。

如果end不是该行的第一个单词,请添加.*以匹配额外的字符。 即:start(.*\n)*?.*end可以找到

start
two
three
four end end
如果你只想替换到第一个end,则需要添加另一个非贪婪操作符:start(.*\n)*?.*?end
历史:在Visual Studio 2017(和早期版本的2019)中,您还可以在查找和替换对话框中使用单行选项Ctrl-Shift-F,如下所示:(?s)start.*end
更多信息请参见此答案的版本历史。

这个代码是可行的,但你需要在 end 前面加上额外的问号,这样它就不会贪婪匹配了。例如:start(.*\n)*.*?end - CAD bloke
5
贪婪版本会在“开始”和“结束”之间匹配尽可能多的字符。如果您想找到紧接着的“结束”,请使用非贪婪版本:(?s)start.*?end,或者 start(.*\n)*?.*?end - Stephan Stamm
1
注意:自Visual Studio 2013以来,此方法已不再适用。请参考Giles Roberts的答案。 - relatively_random
@relatively_random:你在使用(?s)时有困难吗? - Stephan Stamm
1
是的,我做到了。在新版本的VS上它仍然有效吗? - relatively_random
是的。我刚刚在Visual Studio Community 2019(版本16.3.10)中测试过了。也许“查找选项”可以帮助你。 - Stephan Stamm

27

这在Visual Studio 2012中现在可行:

fooPatternToStart.*(.*\n)+?.*barPatternToEnd

观察如何使用 (.*\n)+? 跨多行进行非贪婪匹配。
fooPatternToStart 是你的起始行上的一些正则表达式模式,而 barPatternToEnd 是你要在另一行(可能是许多行)下查找的模式...

这里找到示例。

简单而有效 :)

注:在 VS2012 之前,可用的模式为:fooPatternToStart.(.\n)+@.*barPatternToEnd


4
请注意,Visual Studio 2012在查找/替换中使用与代码中相同的正则表达式引擎,因此上述内容变为:fooPatternToStart.*(.\n)?.*barPatternToEnd。 - Brent
@Brent:可以肯定的是,更新版本的VSTO已经解决了那个问题。 - scrat.squirrel
如果我想在开始和结束之间特定地搜索文本怎么办?像这样?编辑:sprintf.*(.*\n)+?.*log.*(.*\n)+?.*__func__可以搜索sprintf__func__之间的log,谢谢!不过...它似乎会无限制地查找。如果有一种方法可以限制行数就好了。 - Gizmo

19

注意:此答案使用的是 Visual Studio 2012 版本及以前版本中使用的正则表达式语法。在 VS 2013 及以后版本中,正则表达式语法已更改。

你可以在表达式中包含 \n。例如,以下是我用于从自动生成的 SQL 脚本中“清除”非存储过程内容的正则表达式(它将匹配以包含“Object: ”行开头且不为“StoredProcedure”的内容块,然后匹配随后的行直到一个由单词“GO”组成的行):

/\*+ Object\::b:b~(StoredProcedure)(.*\n)#GO\n

注意:换行符取决于文件的格式,因此只能在Unix样式文本中使用\n,在Mac样式文本中使用\r,在Windows样式文本中使用\r\n。 - James Wilkins
2
注意二:同时确保您没有勾选“匹配整个单词”,否则这将无效! - Ed Graham
1
你能否添加一条注释,说明此答案仅适用于Visual Studio 2012及更早版本? - Giles Roberts

4
你可能需要在表达式的结尾处使用 \r\n。

2

非贪婪多行任意字符捕获,Visual Studio 2013+:

.*?\r?\n.*?

在Giles Roberts的回答中,有一种贪心算法版本。

0

对于所有在搜索VS Code时来到这里的人,我使用以下代码匹配从script到任何地方的内容,并且有2个换行符(不包括换行符):

script(.|\n)+?(?=\n\n)

script\n\n替换为它们之间的所有内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接