Multi-line regular expressions in Visual Studio - regex

Is there any way to get Visual Studio to perform a regex replace across multiple lines (let the match cross line boundaries)? I know there are many editors I can use for this, but it seems strange that this feature has been left out of Visual Studio. Am I missing something?

Regular expressions have changed in Visual Studio 2013. https://msdn.microsoft.com/en-us/library/2k3te2cs(v=vs.120).aspx
To match an expression over two lines the code would now be:
StartOfExpression.*\r?\n.*EndOfExpression

Use (.*\n)*? to skip zero or more lines between your expressions.
start(.*\n)*?end
finds
start
two
three
end
? is the non-greedy operator, used to skip as few lines as possible.
If end is not the first word in the line, add .* to match the extra characters. I.e.: start(.*\n)*?.*end finds
start
two
three
four end end
If you only want to replace until the first end, add another non-greedy operator: start(.*\n)*?.*?end.
Historic: In Visual Studio 2017 (and early versions of 2019) you can also use the single line option in the Find and Replace dialog Ctrl-Shift-F like this:
(?s)start.*end
For more see the version history of this answer.

This works today in Visual Studio 2012:
fooPatternToStart.*(.*\n)+?.*barPatternToEnd
See how the (.*\n)+? part does the match across multiple lines, non-greedy.
fooPatternToStart is some regex pattern on your start line, while barPatternToEnd is your pattern to find on another line below, possibly many lines below...
Example found here.
Simple and effective :)
Note: before VS2012, the pattern that worked was: fooPatternToStart.(.\n)+#.*barPatternToEnd

Note: this answer is using the regex syntax used in Visual Studio up to and including VS 2012. In VS 2013 and later, the regex syntax has changed.
You can include \n in the expression. As an example, here is a regex that I use to "clean" auto-generated SQL scripts from anything that is not a stored procedure (it will match text blocks that start with a line containing "Object: " followed by something that is not "StoredProcedure", then matching the following lines up to a line consists of the word "GO"):
/\*+ Object\::b:b~(StoredProcedure)(.*\n)#GO\n

you may need to use \r\n at the end of your expression.

Non-greedy multi-line any character capture, Visual Studio 2013+:
.*?\r?\n.*?
Greedy version in Giles Roberts's answer.

For everyone coming here while searching for VS Code, I use this to match anything from script to anywhere with 2 newlines (newlines excluded):
script(.|\n)+?(?=\n\n)
replace script and \n\n to match everything between them.

Related

Visual Studio hangs searching for regex ^.*$

(To clarify, I'm talking about Ctrl-Shift-F search. Current Document.)
I want to search for lines that don't contain a certain character, like '(', so I figure I need to include ^ and $ indicators to get the entire line. But this just crashes the GUI. Is there a way forward?
Lines without ( should be handled by this:
^[^\(]*$
But this hangs, as does the simpler "^.*$".
Maybe there's another way to find these lines?
EDIT: the proposed "duplicate" question is about C# RegEx class, completely utterly different from Visual Studio 2010 interactive regular expressions.
If you want to match lines, use ^[^\r\n(]*$, where \r and \n are excluded from [^(] – Wiktor Stribiżew Jun 27 at 19:36
This comment is indeed the answer. Apparently old Visual Studio searches could span multiple lines, and ^.*$ thus means start at the beginning of the line, go forward any number of characters up to the end of the document, then stop at the end of a line. These characters can include any number of newlines.
VS apparently didn't efficiently implement this query and hangs interminably.
W.S.'s proposal explicitly excludes newlines from the search parameters, thereby forcing only a single line.
Visual Studio 2012 changes to more conventional regular expression search which limits results to within single lines, so ^.*$ will just fetch all the lines of a document one by one.

Why does a regular expression with a positive lookbehind in Visual Studio cause every second match to be substituted?

Given the following regular expression containing a positive lookbehind (simplified from the one I'm actually trying to use):
(?<=\s|\n)(".*?")
and the following substitution expression:
_T($1)
Visual Studio 2013 will find every matching string but when replacing, will replace the string corresponding to the subsequent match, so will replace every second string.
Furthermore, Replace All does not work and says it cannot find any matching text (even though a Find All will find the relevant strings).
Is this a bug in Visual Studio or am I doing something wrong?
Demo:
TLDR; Visual Studio (VS) search/replace using VS Regexe's have to work with Visual Studio operations and what appears to be a valid regex will not work because of all the moving parts.
Explanation Because there are actually multiple things working against that lookbehind pattern in visual studio. Each of them is working in separately to achieve what you are seeing; but they are individual actions and not a cabal of one thought failure. Let me list them via 1/2/3:
#1: When using any type of lookbehind/ahead in regular expression patterns, one must note that it doesn't capture what it specifies in the lookbehind. The capture happens on what comes after it. So your "Find Next" item doesn't capture the space or linefeed behind it. (It is what you want and this is logical) but see below how the space before it is not captured and each set is highlighted and how that interferes with the whole process.
Stand alone this works and is what is intended, as a search/highlight, but then #2 comes into play.
#2: Visual Studio editor is not a true regex replace operation. Because it is doing a two step operation to do a replace; these steps are not integrated like a code regex replace. Let that sink in.
Step one is a find, step 2 is a replace. Replace all is multiple two step (Find/Replace) operations til end of file from current location.
On this single replace skip issue, on the first press, because Replace Next has to first find the next item, it doesn't replace it; by design It just moves the highlight to the next "XXXXXX" string.
(Press 2) The user thinks Studio is going to replace what is highlighted, but that doesn't happen in this case, because the match pattern states that the current match position must have \s|\n within in it; curses, the lookbehind!
Because it doesn't have \s|\n of the lookbehind in the current selection it must move the text point which is the next location after the current highlight, and if found does a replace there.
To be clear, because the replace operation is sitting on a quote and not a \s|\n (as directed by the pattern), it must move the current pointer to the next \s|\n which it finds it and replaces the text. Note the two clicks in blue that happen to do the
#3: What is interesting is that if one doesn't do the match replacement, $1, but just some text, replace all works, uggg confusing.
Because the replace match $1 is not viable in any individual search/replace step, the replace all the operation subsequently locks up.
Summary
What you want to do is logical, but because the regex replace with a lookbehind is jiggering with the editor pointer and the two step find/replace with regex operation, a conjunction of individual scenarios is causing the whole operation to fail.
One has to design a visual studio regex pattern to work with the #1/#2/#3 editor idiosyncrasies as pointed out above. Keep in mind that VS regex is not true .NET regex parser...just a close one-off.
Is it a bug? Maybe. But IMHO a fix would require a whole redesign of search/replace feature to be more regex centric than plain text search centric (with regex patterns) like it is now.

Why isn't this inverse RegEx match working in Visual Studio?

I have a RegEx:
ConfigurationManager.ConnectionStrings.Item\(\"((?!foo).)*\"
that works in Rubular and matches the second of the two strings as expected:
ConfigurationManager.ConnectionStrings.Item("foo")
ConfigurationManager.ConnectionStrings.Item("bar")
however, if I run the same expression in Visual Studio 2005 - I get no matches. It actually should match every single instance where ConfigurationManager.ConnectionStrings.Item... exists because none of them match the word foo.
Unless of course the inverse expression doesn't work in Visual Studio.
If that's true, how would I go about getting the same result in Visual Studio 2005?
The regex below is adapted from the syntax of regular expression for find and replace feature in Visual Studio, which is not the usual Perl-based regex syntax.
ConfigurationManager.ConnectionStrings.Item\("(~(foo).)*"
~(pattern), according to the description:
Prevent match ~(X) Prevents a match when X appears at this point
in the expression. For example, real~(ity) matches
the "real" in "realty" and "really," but not the
"real" in "reality."
Should work similar to how negative look-ahead (?!pattern) works.

Visual Studio append text to end of lines using find/replace with end line regular expression ($)

I am trying to append some text (e.g. "Fish") to the end of every line in a file using Visual Studio or SQL Server Management Studio using the following settings in the find/replace dialog:
Find what: $
Replace with: Fish
Use Regular expressions: Checked
This mostly does the job, but for a handful of lines it not only appends "Fish" to the end of the line it also puts it at the beginning of the line. I can't discern any pattern to this behaviour it seems to be almost random, with the larger the file the more lines tending to go wrong.
A similar find/replace with ^ (to put text at the beginning of the line) works with no problem.
Anybody know why this is happening? And also, are there any better suggestions for achieving what I want to?
This works in Visual Studio 2012 and 2015:
Find: \r
Replace: Fish\r
Make sure you tick 'Use Regular Expressions' checkbox:
I'm not sure why you're seeing that, but you might try something like:
Find: ^.*$
Replace: \0Fish

How do I convert strings in code to uppercase in Visual Studio?

I'm trying to convert all character strings that match a particular regex in a file to uppercase, but I can't find the syntax to specify that within the 'Find and replace' window in Visual Studio. Is it possible to do this using the Visual Studio regex?
As JaredPar has expained, this cannot be done using a generic regular expression search/replace. However, I guess you should be able to do this using a macro.
It's not possible to do this as a generic replacement using Visual Studio regular expressions. It is possible to re-use the captured text as part of a replacement string using the \n escape sequence where n represents the nth group of captured text. However the regex language only supports limited modifications on this text (mostly justification changes). It doesn't allow you to change case.
Here is a link to the Visual Studio regex language
http://msdn.microsoft.com/en-us/library/2k3te2cs(VS.80).aspx
press alt + 'e' when the find window has focus to enable "regex" searches.
naturally, you can't 'program' a set of replacement options to insert based on what is found. Each replacement set would require one pass.