sclarke81
sclarke81

Reputation: 1769

Regex to replace spaces in file link

I'm processing some text using C# and I need a regex to replace the spaces in a file link with %20. So given this text:

/*
**  2 > 1
**  1 < 2 
**  <file:\\\server\dir one\dirtwo\file name.txt>
**  <just because>
**  1 < 2
**  2 > 1
**  <file:\\\server\dir one\dirtwo\file name.txt>
**  2 > 1
*/

The result would be:

/*
**  2 > 1
**  1 < 2 
**  <file:\\\server\dir%20one\dirtwo\file%20name.txt>
**  <just because>
**  1 < 2
**  2 > 1
**  <file:\\\server\dir%20one\dirtwo\file%20name.txt>
**  2 > 1
*/

So far I've come up with this pattern \x20(?=(?:(?!<file:).)*>) but it matches some of the spaces that are outside of the file link.

Ideally I'd like to do this just using regex. The text I'm modifying is the current document open in Visual Studio (I've created a VS extension). For some other text changes I'm using the ReplacePattern method in EnvDTE.TextDocument. I don't have much experience writing extensions so this seemed a lot simpler than anything else I could come up with (I did look at using edit points).

Solution

There seems to be an issue with using lookbehind or lookahead in a regex using the TextDocument.ReplacePattern method which causes an exception to be raised. Using the same expression in Regex.Replace works as expected. If it wasn't for this issue then the solution(s) provided by Wiktor Stribiżew would be perfect.

To keep things simple I've implemented the following which does the job:

bool patternReplaced;
do
{
   patternReplaced = activeDoc.ReplacePattern(@"(<file:\\{3}.*)\s(\S+>)", @"$1%20$2", (int)vsFindOptions.vsFindOptionsRegularExpression);
} while (patternReplaced);

Upvotes: 2

Views: 156

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627087

You can use a Regex.Replace to match the <file:...> substrings and replace the spaces using the match evaluator:

var res = Regex.Replace(str, @"<file:\\{3}[^>]+>", m => m.Value.Replace(" ", "%20"));

See the IDEONE demo

Note that in case there are more than just spaces to escape, you can consider using Uri.EscapeUriString(m.Value) (with another regex, like @"(?<=<file:\\{3}[^<>]*)[^<>\\]+").

Another solution using infinite width lookbehind:

@"(?<=<file:\\{3}[^<>]*)\s"

and replace with %20.

See this regex demo

Upvotes: 1

Related Questions