1

I came across How to search and replace exact matching strings only. However, it doesn't work when there are words that start with @. My fiddle here https://dotnetfiddle.net/9kgW4h

string textToFind = string.Format(@"\b{0}\b", "@bob");
Console.WriteLine(Regex.Replace("@bob!", textToFind, "me"));// "@bob!" instead of "me!"

Also, in addition to that what I would like to do is that, if a word starts with \@ say for example \@myname and if I try to find and replace @myname, it shouldn't do the replace.

Community
  • 1
  • 1
Frenz
  • 687
  • 1
  • 10
  • 22
  • 2
    This question has nothing to do with [escaping](http://stackoverflow.com/questions/20505914/escape-special-character-in-regex), but with word boundaries. Did you intend to match a `textToFind` only when not preceded and not followed with a word char? Try `@"(?<!\w){0}(?!\w)"` regex inside `string.Format` and replace with `replace.Replace("$", "$$")` (if your replacement string may contain `$` symbols that you want to treat as literal chars). – Wiktor Stribiżew Jan 16 '17 at 07:19
  • 1
    As for the "bonus" part, it is not quite clear, but perhaps, `@"(?<!\w)(?<!(?<!\\)\\(?:\\\\)*){0}(?!\w)"` will do? – Wiktor Stribiżew Jan 16 '17 at 07:57
  • I intent to match exact words. So if I find '@bob' and try to replace it should match only '@bob' and not '@bob.com' or \@bob. Similarly for \@bob should match only \@bob – Frenz Jan 16 '17 at 23:01

1 Answers1

3

I suggest replacing the leading and trailing word boundaries with unambiguous lookaround-based boundaries that will require whitespace chars or start/end of string on both ends of the search word, (?<!\S) and (?!\S). Besides, you need to use $$ in the replacement pattern to replace with a literal $.

I suggest:

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        string text = @"It is @google.com or @google w@google \@google \\@google";
        string result = SafeReplace(text,"@google", "some domain", true);
        Console.WriteLine(result);
    }


    public static string SafeReplace(string input, string find, string replace, bool matchWholeWord)
    {
        string textToFind = matchWholeWord ? string.Format(@"(?<!\S){0}(?!\S)", Regex.Escape(find)) : find;
        return Regex.Replace(input, textToFind, replace.Replace("$","$$"));
    }
}

See the C# demo.

The Regex.Escape(find) is only necessary if you expect special regex metacharacters in the find variable value.

The regex demo is available at regexstorm.net.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks for your answer. However, in this case it replaces @google.com, since the find string is '@google' it should be only matching that and not any other word that contains '@google'. – Frenz Jan 16 '17 at 22:55
  • Do you mean [`(?<![\w\\])@google(?!\w)`](http://regexstorm.net/tester?p=%28%3f%3c!%5b%5cw%5c%5c%5d%29%40google%28%3f!%5cw%29&i=It+is+%40google.com+or+%40google+w%40google+%5c%40google+%5c%5c%40google&r=%241some+domain)? – Wiktor Stribiżew Jan 16 '17 at 23:18
  • Almost there, it shouldn't match '@google.com'. It should match only '@google' and nothing else. So when '@google' followed by any special character it doesn't work. – Frenz Jan 16 '17 at 23:30
  • 1
    So, a word boundary in that case is any whitespace? Then you need [`(?<!\S)@google(?!\S)`](http://regexstorm.net/tester?p=%28%3f%3c!%5cS%29%40google%28%3f!%5cS%29&i=It+is+%40google.com+or+%40google+w%40google+%5c%40google+%5c%5c%40google&r=%241some+domain). – Wiktor Stribiżew Jan 16 '17 at 23:32
  • Perfect. That's exactly what I wanted. Thanks a lot. Appreciate your help. – Frenz Jan 16 '17 at 23:45
  • I don't think i need to do replace.Replace("$","$$") now is it? – Frenz Jan 16 '17 at 23:46
  • If your *replace* variable hold literal user-defined value (the value you do not know beforehand), you must escape the special dollar sign in the replacement pattern to avoid issues. – Wiktor Stribiżew Jan 17 '17 at 07:03