Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

enter image description here

like image 633
James Bateson Avatar asked Oct 19 '22 16:10

James Bateson


1 Answers

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.

Individual matches using the lookbehind

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.

enter image description here

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.

enter image description here

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.

like image 154
ΩmegaMan Avatar answered Oct 29 '22 18:10

ΩmegaMan