C# Regex Replacing Template content - c#

While using Regex to replace keywords with value in a template, I tested the following code.
string input = "Welcome {{friend}} Get my new {{id}} with {{anonymous}} People";
Dictionary<string, string> mydict = new Dictionary<string, string> ();
mydict.Add("friend", "<<My Friend>>");
mydict.Add("id", "<<Your ID>>");
string pattern = #"(?<=\{{2})[^}}]*(?=\}{2})";// #"\{{2}^(.*?)$\}{2}";//"^[{{\\w}}]$";
//var m = Regex.Match(input, #"\{{(.*)\}}");
string regex = Regex.Replace(input, pattern, delegate(Match match) {
string v = match.ToString();
return mydict.ContainsKey(v) ? mydict[v] : v;
});
Console.WriteLine(regex);
The curley braces still remain in the output which is not desired
I need <<My Friend>> instead of {{ <<My Friend>> }}.
I would appreciate your suggestion.

Braces remain in the original text because you are using zero-width lookahead and lookbehind constructs. This leaves the content matched by (?<=...) and (?=...) outside regex's captured value, so it does not get replaced.
To fix this problem remove lookahead and lookbehind from your regex, put a capturing group around the text of the tag, and use it to search replacement dictionary:
string pattern = #"\{{2}([^}}]*)\}{2}";
...
var v = match.Group[1].Value;
return mydict.ContainsKey(v) ? mydict[v] : v;

You may use a simple {{(.*?)}} regex and use the Group 1 vlaue to check for the dictionary match:
string pattern = #"{{(.*?)}}";
string regex = Regex.Replace(input, pattern, delegate(Match match) {
string v = match.Groups[1].Value;
return mydict.ContainsKey(v) ? mydict[v] : v;
});
// => Welcome <<My Friend>> Get my new <<Your ID>> with anonymous People
The same code with a lambda expression:
string regex = Regex.Replace(input, pattern, x =>
mydict.ContainsKey(match.Groups[1].Value) ?
mydict[match.Groups[1].Value] : match.Groups[1].Value;
});
See the C# demo.
Note that [^}}] does not mean match any text other than }}, it just matches any char other than }, same as [^}], so .*? is preferable in this case. Or even \w+ if you only have letters, digits and underscores in between {{ and }}.

Related

How to use regex to find variable name beginning with # in a string expression?

The programmer hope to get two variables day1 and day2 by using regex, all the other variables in string expression beginning with the character # too.
The example of a string expression: #day1 - #day2 > 3
Thanks!
You can simply use positive lookahead here.
string = "#day1 - #day2 > 3";
Regex regex = new Regex("(?<=#)\\w+", RegexOptions.Compiled);
var match = regex.Matches(a);
foreach( var val in match )
{
Console.WriteLine(val);
}
val contains the match values.
You could use a lookbehind to get the variable names, like so:
var regex = new Regex("(?<=#)\\w+");
This will get the words preceded by an # sign

Remove Adjacent Space near a Special Character using regex

Using regex want to remove adjacent Space near replacement Character
replacementCharcter = '-'
this._adjacentSpace = new Regex($#"\s*([\{replacementCharacter}])\s*");
MatchCollection replaceCharacterMatch = this._adjacentSpace.Matches(extractedText);
foreach (Match replaceCharacter in replaceCharacterMatch)
{
if (replaceCharacter.Success)
{
cleanedText = Extactedtext.Replace(replaceCharacter.Value, replaceCharacter.Value.Trim());
}
}
Extractedtext = - whi, - ch
cleanedtext = -whi, -ch
expected result : cleanedtext = -whi,-ch
You can use
var Extactedtext = "- whi, - ch";
var replacementCharacter = "-";
var _adjacentSpace = new Regex($#"\s*({Regex.Escape(replacementCharacter)})\s*");
var cleanedText = _adjacentSpace.Replace(Extactedtext, "$1");
Console.WriteLine(cleanedText); // => -whi,-ch
See the C# demo.
NOTE:
replacementCharacter is of type string in the code above
$#"\s*({Regex.Escape(replacementCharacter)})\s*" will create a regex like \s*-\s*, Regex.Escape() will escape any regex-special char (like +, (, etc.) correctly to be used in a regex pattern, and the whole regex simply matches (and captured into Group 1 with the capturing parentheses) the replacementCharacter enclosed with zero or more whitespaces
No need using Regex.Matches, just replace all matches if there are any, that is how Regex.Replace works.
_adjacentSpace is the compiled Regex object, to replace, just call the .Replace() method of the regex object instance
The replacement is a backreference to the Group 1 value, the - char here.

Regular expression to replace string except in sqaure brackets

Need to replace all forward-slash (/) with > except for the ones in the square brackets
input string:
string str = "//div[1]/li/a[#href='https://www.facebook.com/']";
Tried pattern (did not work):
string regex = #"\/(?=$|[^]]+\||\[[^]]+\]\/)";
var pattern = Regex.Replace(str, regex, ">");
Expected Result:
">>div[1]>li>a[#href='https://www.facebook.com/']"
Your thinking was good with lookbehind but instead positive use negative.
(?<!\[[^\]]*)(\/)
Demo
After updating your c# code
string pattern = #"(?<!\[[^\]]*)(\/)";
string input = "//div[1]/li/a[#href='https://www.facebook.com/']";
var result = Regex.Replace(input, pattern, ">");
You will get
>>div[1]>li>a[#href='https://www.facebook.com/']
If you're willing to also use String.Replace you can do the following:
string input = "//div[1]/li/a[#href='https://www.facebook.com/']";
string expected = ">>div[1]>li>a[#href='https://www.facebook.com/']";
var groups = Regex.Match(input, #"^(.*)(\[.*\])$")
.Groups
.Cast<Group>()
.Select(g => g.Value)
.Skip(1);
var left = groups.First().Replace('/', '>');
var right = groups.Last();
var actual = left + right;
Assert.Equal(expected, actual);
What this does is split the string into two groups, where for the first group the / is replaced by > as you describe. The second group is appended as is. Basically, you don't care what is between square brackets.
(The Assert is from an xUnit unit test.)
You could either match from an opening till a closing square bracket or capture the / in a capturing group.
In the replacement replace the / with a <
Pattern
\[[^]]+\]|(/)
\[[^]]+\] Match from opening [ till closing ]
| Or
(/) Capture / in group 1
Regex demo | C# demo
For example
string str = "//div[1]/li/a[#href='https://www.facebook.com/']";
string regex = #"\[[^]]+\]|(/)";
str = Regex.Replace(str, regex, m => m.Groups[1].Success ? ">" : m.Value);
Console.WriteLine(str);
Output
>>div[1]>li>a[#href='https://www.facebook.com/']

Regex match and replace operators in math operation

Given an input string
12/3
12*3/12
(12*54)/(3/4)
I need to find and replace each operator with a string that contains the operator
some12text/some3text
some12text*some2text/some12text
(some12text*some54text)/(some3text/some4text)
practical application:
From a backend (c#), i have the following string
34*157
which i need to translate to:
document.getElementById("34").value*document.getElementById("157").value
and returned to the screen which can be run in an eval() function.
So far I have
var pattern = #"\d+";
var input = "12/3;
Regex r = new Regex(pattern);
var matches = r.Matches(input);
foreach (Match match in matches)
{
// im at a loss what to match and replace here
}
Caution: i cannot do a blanket input.Replace() in the foreach loop, as it may incorrectly replace (12/123) - it should only match the first 12 to replace
Caution2: I can use string.Remove and string.Insert, but that mutates the string after the first match, so it throws off the calculation of the next match
Any pointers appreciated
Here you go
string pattern = #"\d+"; //machtes 1-n consecutive digits
var input = "(12*54)/(3/4)";
string result = Regex.Replace(input, pattern, "some$0Text");
$0 is the character group matching the pattern \d+. You can also write
string result = Regex.Replace(input, pattern, m => "some"+ m.Groups[0]+ "Text");
Fiddle: https://dotnetfiddle.net/JUknx2

replace placeholder with value from hash table

I have text with placeholder as below
"My name is |#NAME#| My Age is |#AGE#|"
and I have < string, string> Dictionary that contain each placeholder and its value based on the that dictionary
so I need to replace each placeholder with its value
I tried this but it's not working
Regex regex = new Regex(#"\|#([^\#|]+)\}", RegexOptions.Compiled);
string newStr = regex.Replace(
originalString,
delegate(Match match)
{
return placeholder[match.Groups[1].Value];
});
In your regex, \} matches a } that is missing in your input.
You need to use
#"\|#(.+?)#\|"
See the regex demo
Details:
\|# - a |# char sequence
(.+?) - capturing group #1 matching any one or more chars other than a newline
#\| - a #| char sequence.
In the code, you may use
string newStr = Regex.Replace(
originalString,
#"\|#(.+?)#\|",
match => placeholder.ContainsKey(match.Groups[1].Value) ?
placeholder[match.Groups[1].Value] : match.Value
);

Categories