Reputation: 676
Lets say I have the following regex:
Console.writeline.+(?!;)
I want to find any line that contains "console.writeline" followed by any character one or more times but does not end with a semicolon.
When I test this regex with the following string:
Console.WriteLine("Final total count of missing VMs: {0}", missingVms.Count);
It matches. However that string ends in a semicolon so shouldn't it not match?
I realize I could use [^;]
but I was more curious as to why looking for a semicolon doesn't seem to work with negative lookaheads in .NET
Edit: To clarify:
Lets say I am using Visual Studio's Find and Replace tool and I want to find and comment out every instance of Console.WriteLine(...)
. However, I can wind up with situations where Console.WriteLine(...)
goes across multiple lines like so:
Console.WriteLine("Adding drive to VM with ID: {0}. Drive HostVMID is {1}",
vm.ID, drive.HostVmId);
These can go on for 2, 3, 4, etc lines and finally end with );
to close the statement. Then I can have other lines that are immediately followed by important blocks of code:
Console.WriteLine("Creating snapshot for VM: {0} {1}", dbVm.ID, dbVm.VmName);
dbContext.Add(new RTVirtualMachineSnapshot(dbVm));
So what I want to do is come up with a regex statement that will find both the first type of instances of Console.WriteLine
as well as simple single-line instances of it.
The Regex that I got from one of the answers to this question was
Console\.writeline(?>.+)(?<!;)
Which will match any line that contains Console.WriteLine
but does not end with a semicolon. However I need it to continue on until it finally does reach a closing parenthesis followed by a semicolon.
Ive tried the following regex:
(Console\.writeline(?>.+)(?<!\);)
However I think thats incorrect because it still only matches the first line and doesnt capture the following lines when the writeline spans multiple lines.
At the end of the day I want to be able to capture a full Console.writeline statement regardless of how many lines it spans using Visual Studio's find and replace feature and I am a little confused on the regex I would need to use to do this.
Upvotes: 2
Views: 386
Reputation: 627101
You can use the following regex with a lookbehind:
Console\.writeline(?>.+)(?<!;)
Here is a demo (note case insensitive flag)
The regex you use Console.writeline.+(?!;)
checks for ;
only after the last character and thus returns true and you get a whole line matched. A lookbehind (?<!;)
will check for a ;
before the end of line. But to make sure the line with last ;
does not match, you need to use an atomic group (?>.+)
to avoid backtracking. If you do not use an atomic group, backtracking will occur and the last character will get tested and the partial match will be returned.
UPDATE
To comment out Console.WriteLine
s in VS Find and Replace you can use
Console\.writeline\s*\([\s\S\r]+?\);(?=$|\r?\n)
or (the same, but an unroll-the-loop technique compliant, with optional whitespace to make it safer):
Console\.writeline\s*\([^)]*(?:\)(?!\s*;\s*(?:$|\r?\n))[^)]*)*\)\s*;\s*(?=$|\r?\n)
and replace with
/* $0 */
In VS Find and Replace, you should use [\s\S\r]
to match any symbol including a newline.
Upvotes: 4