2

I have the following text:

input = "text, *text*, text, text, (text), [text], [text](http://.....) *text*, text, text, (text), [text]"

I'm trying to replace characters '_', '*', '[', ']', '(', ')' to '\_', '\*' etc.

I'm writing:

pattern = @"(?<!\[(?<text>.*)\]\((?<url>.*))([[\]\(\)*_])";

input = Regex.Replace(input, pattern, @"\$1");

System output: "text, \*text\*, text, text, \(text\), \[text\], \[some\_text with \_ \* \]\(http://.....) \*text\*, text, text, \(text\), \[text\]"

How to make sure that the design of the link []() doesn't change? i.e. it would look like:

desired output:"text, \*text\*, text, text, \(text\), \[text\], [some\_text with \_ \*](http://.....) \*text\*, text, text, \(text\), \[text\]"
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
di_va
  • 35
  • 4
  • Is your regex matching all the chars you need to escape? Is it related to [Escaped character on Telegram Bot API 4.5 MarkdownV2 gives trouble for hyper link](https://stackoverflow.com/questions/60130062/escaped-character-on-telegram-bot-api-4-5-markdownv2-gives-trouble-for-hyper-lin?) – Wiktor Stribiżew Oct 21 '21 at 15:40
  • @WiktorStribiżew, I didn’t write all the characters, because I tried to solve the problem with the link, but I don't quite understand how to solve it. I tried: (? <! \ [(? . *) \] \ ((? . *)) ([| * {} # + = \ -_.! ~> `]), but it still worked like this: \ [... \\] \ (url \\) – di_va Oct 21 '21 at 15:51
  • Please format the question with backticks around your code. It is not clear what is escaped and what is not. Check my example edit. – Wiktor Stribiżew Oct 21 '21 at 15:54
  • @WiktorStribiżew, I fixed the format, thanks for the example – di_va Oct 21 '21 at 16:08

1 Answers1

1

You need to match and capture the markdown link part, and just match the chars you need to escape, and then use a match evaluator in the replacement part:

var input = "text, *text*, text, text, (text), [text], [some_text with _*](http://.....) *text*, text, text, (text), [text]";
var pattern = @"(\[[^][]*]\([^()]*\))|[][()*_]";
Console.WriteLine(Regex.Replace(input, pattern, m => 
    m.Groups[1].Success ? m.Groups[1].Value : $@"\{m.Value}"));

See the C# demo. Details:

  • (\[[^][]*]\([^()]*\)) - Capturing group 1 matching [, then zero or more chars other than [ and ] (with [^][]*), then a ] char, (, then zero or more chars other than ( and ) (with [^()]*) and then a ) char
  • | - or
  • [][()*_] - a character class that matches: ] (note it is not escaped because it is the first char in the character class), [, (, ), * or _ chars.

The m => m.Groups[1].Success ? m.Groups[1].Value : $@"\{m.Value}" replacement replaces the match found with Group 1 value if Group 1 matched, else, the replacement is the match value (the special char defined in the character class) with a \ prepended.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thank you very much, you helped me a lot, but for example, if the text for the link has the same signs, how can they be escaped, [Hello_World*](url) ([Hello\_World\*](url)? – di_va Oct 21 '21 at 16:27
  • @di_va Then use `var pattern = @"\[([^][]*)]\(([^()]*)\)|[][()*_]";` and then `m => m.Groups[1].Success ? $@"[{Regex.Replace(m.Groups[1].Value, @"[()_*]", @"\$&")}]({Regex.Replace(m.Groups[2].Value, @"[()_*]", @"\$&")})" : $@"\{m.Value}")` – Wiktor Stribiżew Oct 21 '21 at 16:56
  • Can I ask a question? I put into [text - # { } ](url) characters: `#`, `{`, `}` `-` but it doesn't escaped it, why? And added this character into pattern – di_va Oct 21 '21 at 23:44
  • @di_va It depends where you "put" it. It must be `[][()*_-]`. – Wiktor Stribiżew Oct 21 '21 at 23:48
  • I put it in last structure [][(){}*_|#+=.!\-~>] but they didn't ecsaped – di_va Oct 21 '21 at 23:50
  • @di_va At this point, I do not not see an issue. Please share a [link to C# demo](https://ideone.com/rHlZ11). – Wiktor Stribiżew Oct 21 '21 at 23:52
  • In the title of the link, I inserted characters that need to be escaped, but they are not escaped and that is an issue [link](https://ideone.com/odbdMP) – di_va Oct 21 '21 at 23:59
  • I found my mistake, sorry, I'm just new to regex – di_va Oct 22 '21 at 00:12
  • @di_va Right, the pattern must be something like `@"\[([^][]*)]\(([^()]*)\)|[][(){}*_|#+=.!~>-]"` and then inside the match evaluator, it must be `@"[][(){}*_|#+=.!~>-]"` ([demo](https://ideone.com/h8RvMI)). – Wiktor Stribiżew Oct 22 '21 at 06:38