return string based on wildcard in c# - c#

I have tried to find a method in c# to return a string of a wildcard match, however I can only find information on how to return if it contains the wildcard match, not the string the wildcard match represents.
For example,
var myString = "abcde werrty qweert";
var newStr = MyMatchFunction("a*e", myString);
//myString = "abcde"
How would I create MyMatchFunction? I have searched around on stackoverflow, but everything that has to do with c# and wildcard is just returning boolean values on if the string contains the wildcard string, and not the string it represents.

Have you considered using Regex?
For instance, with the pattern a.*?e, you could achieve this effect
string sample = "abcde werrty qweert";
string pattern = "a.*?e";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = rgx.Matches(sample);
foreach (Match match in matches)
Console.WriteLine(match.Value);
Which would print out
abcde

Default of wildcard search for "abcde werrty qweert" with pattern of "a*b" will returns "abcde werrty qwee", but you can use gready search for the result of "abcde".
Function for WildCard match using Regex:
public static string WildCardMatch(string wildcardPattern, string input, bool Greedy = false)
{
string regexPattern = wildcardPattern.Replace("?", ".").Replace("*", Greedy ? ".*?" : ".*");
System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(input, regexPattern,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
return m.Success ? m.Value : String.Empty;
}
Result:
var myString = "abcde werrty qweert";
var newStr = WildCardMatch("a*e", myString);
//newStr = "abcde werrty qwee"
newStr = WildCardMatch("a*e", myString, Greedy: true);
//newStr = "abcde"

Related

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

Get the Number from a string

I want to trim a string and get the number between special characters.
For example there is a string BC/PO/88/2018 from it i want to get 88.
you can make use of regular expression and extract number
Match match = Regex.Match("BC/PO/88/2018 f" , #"(\d+)");
if (match.Success) {
return int.Parse(match.Groups[0].Value);
}
other way is you can do with the help of String.Split as suggested in comments if you are sure about string coming as input i.e. sure about format of string.
You could use Regular Expressions:
string strRegex = #"[A-Z]{2}/[A-Z]{2}/(?<MyNumber>[0-9]*)/[0-9]{4}";
Regex myRegex = new Regex(strRegex, RegexOptions.None);
string strTargetString = #"BC/PO/88/2018";
foreach (Match myMatch in myRegex.Matches(strTargetString))
{
if (myMatch.Success)
{
// Add your code here
}
}

How to Regex match a "/" in C#

I would like the "matched" bool to be true after executing this:
string urlSegment = "whatever('id')/"
string regexPattern = ?;
bool matched = Regex.Match(urlSegment, regexPattern, RegexOptions.IgnoreCase).Success
How do I escape the forward slash so I can have whatever followed by "('" followed by whatever id followed by "')/"? (something like regexPattern = "('*')/").
After the edit, here's my proposed pattern: .+\('(.*)'\)/
This will match any set of characters followed by parentheses and single quotes wrapping any set of characters. RegexPal
Original answer:
There's no need to escape: DotNetFiddle
string urlSegment = "whatever('id')/";
string regexPattern = "/";
bool matched = Regex.Match(urlSegment, regexPattern, RegexOptions.IgnoreCase).Success;
Also this is a very simple match. A regex is a little overkill. You can just use Contains() to see if the string contains a second string. This is shown in the fiddle.
You can extract the id with like this :
string urlSegment = "whatever('id')/";
string regexPattern = #"whatever\('(?<id>.+)'\)/";
Match match = Regex.Match(urlSegment, regexPattern, RegexOptions.IgnoreCase);
bool matched = match.Success;
string id = match.Groups["id"].Value;

Regex for a special string pattern on multiple levels

I need to evaluate a string pattern that is something like as given below and I am quite new at writing such complex expressions
<%(ddlValue){DropDownList}[SelectedValue]%>
// this has three part (Control Name) {Control Type} [Control Property]
I tried a whole lot of regex and other tools like RegExr but anything did not worked. I have to do this on four levels, that is as given below in the code. So here is what I have done:
string regex = "/[<%](.*?)[%>]/g"; // Regex to match "<% %>" pattern
Match mtch = Regex.Match(strQuery, regex, RegexOptions.Singleline);
string strControlName = "";
string strControlType = "";
string strControlProp = "";
if (mtch.Success)
{
string strVal = mtch.Value;
Match mtchControlName = Regex.Match(strVal, "/[(]\S)/");
// Regex to match "()" i.e. control name ("ddlValue" in above example)
if (mtchControlName.Success)//Match control Name
{
strControlName = mtchControlName.Value;
Match mtchControlType = Regex.Match(strVal, "/[{]\s[}]/");
// Regex to match "[]" i.e. control type
if (mtchControlType.Success) // Match Control Type
{
strControlType = mtchControlType.Value;
Match mtchControlProp = Regex.Match(strVal, "/[(]\S[)]/");
// Regex to match "[]" i.e. control property
if (mtchControlProp.Success) // Match Control Prop
{
strControlProp = mtchControlProp.Value;
}
}
}
}
You can do this in a single regex. Being as specific as possible, you could do this:
Regex regexObj = new Regex(
#"\( # Match (
( # Capture in group 1:
[^()]* # Any number of characters except ()s
) # End of group 1
\) # Match )
\{([^{}]*)\} # The same for {...} into group 2
\[([^\[\]]*)\] # The same for [...] into group 3",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
Then you case use
Match matchResults = regexObj.Match(subjectString);
to get a Match object. Access the submatches via
matchResults.Groups(n).Value // insert 1, 2 or 3 for n
See it live on regex101.com.
You can use capturing groups in one expression to capture all groups together:
String input = "<%(ddlValue){DropDownList}[SelectedValue]%>";
String pattern = #"<%\((.+)\)\{(.+)\}\[(.+)\]%>";
Match m = Regex.Match(input, pattern);
if (m.Groups.Count == 4)
{
string firstpart = m.Groups[1].ToString();
string secondpart = m.Groups[2].ToString();
string thirdpart = m.Groups[3].ToString();
}
You could use named groups. It makes the code more readable.
Match m = Regex.Match(inputData, #"^<%\((?<ddlValue>[^)]+)\){(?<DropDownList>[^}]+)}\[(?<SelectedValue>[^\]]+)\]%>$");
if (m.Groups.Count == 4)
{
string firstpart = m.Groups["ddlValue"].ToString();
string secondpart = m.Groups["DropDownList"].ToString();
string thirdpart = m.Groups["SelectedValue"].ToString();
}

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