replace placeholder with value from hash table - c#

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
);

Related

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.

C# Regex Replacing Template content

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 }}.

Regex MatchEvaluator doesn't work with words contains "_" underscore

I am trying to match and format output regex result. I have a words array e.g:
var resultArray = new List {"new", "new_"}; // notice the word with underscore
But when i try to search a sentence like this:
New Law_Book_with_New_Cover
it does match the with the first word "New" but not the middle one with "New_". here is my code
if (resultArray.Count > 0)
{
string regex = "\\b(?:" + String.Join("|", resultArray.ToArray()) + ")\\b";
MatchEvaluator myEvaluator = new MatchEvaluator(GetHighlightMarkup);
return Regex.Replace(result, regex, myEvaluator, RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase);
}
private static string GetHighlightMarkup(Match m)
{
return string.Format("<span class=\"focus\">{0}</span>", m.Value);
}
And yes i did tried escaping the word "\New_" but no luck still.
What am i missing ?
It seems you need to match your items only if they are not enclosed with letters.
You may replace the word boundaries in your regex with lookarounds:
string regex = #"(?<!\p{L})(?:" + String.Join("|", resultArray.ToArray()) + #")(?!\p{L})";
where \p{L} matches any letter, (?<!\p{L}) requires the absence of a letter before the match, and (?!\p{L}) disallows a letter after the match.

Check multiple words in a string using Contains method

I want to check multiple words in a string and want to replace them. Suppose that my string is
str= 20148(R)/(work)24553(r)
if(str.contains(("R)" || str.Contains("(work)"))
{
//Here I have to replace (R) and (Work) with space "".
// so that my string should be like this 20148/24553
}
How can check multiple words not by using loops, and in one flow.
I am new to c#. Please help me out
You don't need the if, just do:
var newStr = str.Replace("(R)"," ").Replace("(work)"," ");
If you want a space as you say or:
var newStr = str.Replace("(R)",string.Empty).Replace("(work)",string.Empty);
If you want an empty string.
Put R and r inside a character class to match both letters.
string str = "20148(R)/(work)24553(r)";
string result = Regex.Replace(str, #"\((?:[Rr]|work)\)", "");
Console.WriteLine(result);
IDEONE
OR
string str = "20148(R)/(work)24553(r)";
string result = Regex.Replace(str, #"(?i)\((?:R|work)\)", "");
Console.WriteLine(result);
IDEONE
Pattern Explanation:
(?i) (i modifier) would turn on the case-insensitive mode. So it would match both upper and lowercase letters.
\( Matches a literal ( symbol.
(?:) Non-capturing group.
R|work Matches a letter R or string work.(case-insensitive match)
\) Matches a literal ) symbol.
You could use the Regex.Replace method.
string str = "20148(R)/(work)24553(r)";
string str2 = Regex.Replace(str, "[(](?:R|work)[)]", "", RegexOptions.IgnoreCase);
Console.Writeline(str2); //prints 20148/24553
This says take the string str and match the pattern [(R|work)] and replace any instances with "" ignoring the case of the input string when doing the comparison (so it matches (R) and (r)).
With regex you can replace this
[(]\b(?:R|work)\b[)]
With empty string ""
Edit:
string str1 = "20148(R)/(work)24553(r)";
string str2 = Regex.Replace(str1, "[(]\b(?:R|work)\b[)]", "", RegexOptions.IgnoreCase);
Console.Writeline(str2);

Regex replace with separate replacement depending on the match

Suppose if I have a dictionary (word and its replacements) as :
var replacements = new Dictionary<string,string>();
replacements.Add("str", "string0");
replacements.Add("str1", "string1");
replacements.Add("str2", "string2");
...
and an input string as :
string input = #"#str is a #str is a [str1] is a &str1 #str2 one test $str2 also [str]";
Edit:
Expected output :
string0 is a string0 is string0 is string1 string2 one test string2
I want to replace all occurances of '[CharSymbol]word' with its corresponding entry/value from the dictionary.
where Charsymbol can be ##$%^&*[] .. and also ']' after the word is valid i.e. [str] .
I tried the following for replace
string input = #"#str is a #str is a [str1] is a &str1 #str2 one test $str2 also [str]";
string pattern = #"(([#$&#\[]+)([a-zA-Z])*(\])*)"; // correct?
Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
// string outputString = re.Replace(input,"string0");
string newString = re.Replace(input, match =>
{
Debug.WriteLine(match.ToString()); // match is [str] #str
string lookup = "~"; // default value
replacements.TryGetValue(match.Value,out lookup);
return lookup;
});
How do i get the match as str , str1 etc. i.e. word without charsymbol.
Change your regex to this:
// Move the * inside the brackets around [a-zA-Z]
// Change [a-zA-Z] to \w, to include digits.
string pattern = #"(([#$&#\[]+)(\w*)(\])*)";
Change this line:
replacements.TryGetValue(match.Value,out lookup);
to this:
replacements.TryGetValue(match.Groups[3].Value,out lookup);
Note: Your IgnoreCase isn't necessary, since you match both upper and lower case in the regex.
Does this suit?
(?<=[##&$])(\w+)|[[\w+]]
It matches the following in your example:
#str is a #str is a [str] is a &str1 #str2 one test $str2
Try this Regex: ([#$&#\[])[a-zA-Z]*(\])?, and replace with string0
your code should be like this:
var replacements = new Dictionary<string, string>
{
{"str", "string0"},
{"str1", "string1"},
{"str2", "string2"}
};
String input="#str is a #str is a [str] is a &str #str can be done $str is #str";
foreach (var replacement in replacements)
{
string pattern = String.Format(#"([#$&#\[]){0}(\])?", replacement.Key);
var re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
string output = re.Replace(input,
String.Format("{0}", replacement.Value));
}

Categories