Taking a piece of a REGEX and setting it to a String - c#

Is there any way to take a part out of a regex? Let's say I have a match for this
\s*(string)\s*(.*\()\s*(\d*)\)\s*;?(.*)
and I want to change it like this
Regex.Replace(line, #"\s*(string)\s*(.*\()\s*(\d*)\)\s*;?(.*)", "$1 $2($3) // $4", RegexOptions.IgnoreCase);
Is there any way I can grab the $4 by itself and set it equal to some string variable?
Let's say the regex match is: string (55) ;comment
In this case I'd like to get the word comment only and set it to a string without going through the String.Split function. Ultimately, though, I'd just like to get the digits between the parentheses.

There's an overload for the Replace method which takes a MatchEvaluator delegate:
string pattern = "...";
string result = Regex.Replace(line, pattern, m =>
{
int digits = 0;
string comment = m.Groups[4].Value; // $4
int.TryParse(m.Groups[3].Value, out digits); // $3
return string.Format("{0} {1}({2}) // {3}",
m.Groups[1].Value, m.Groups[2].Value, digits, comment);
}, RegexOptions.IgnoreCase);
Hope this helps.

Yes, if I understand the question correctly:
var re = new Regex(#"\s*(string)\s*(.*\()\s*(\d*)\)\s*;?(.*)");
var match = re.Match(input);
if (match.Success)
{
int i = match.Groups[4].Index;
int n = match.Groups[4].Length;
input = input.Substring(0, i) + replacementString + input.Substring(i + n);
}

Related

Replace only 'n' occurences of a substring in a string in C#

I have a input string like -
abbdabab
How to replace only the 2nd, 3rd and subsequent occurances of the substring "ab" with any random string like "x" keeping the original string intact. Example in this case -
1st Output - xbdabab 2nd Output - abbdxab 3rd Output - abbdabx and so on...
I have tried using Regex like -
int occCount = Regex.Matches("abbdabab", "ab").Count;
if (occCount > 1)
{
for (int i = 1; i <= occCount; i++)
{
Regex regReplace = new Regex("ab");
string modifiedValue = regReplace.Replace("abbdabab", "x", i);
//decodedMessages.Add(modifiedValue);
}
}
Here I am able to get the 1st output when the counter i value is 1 but not able to get the subsequent results. Is there any overloaded Replace method which could achieve this ? Or Can anyone help me in pointing where I might have gone wrong?
You can try IndexOf instead of regular expressions:
string source = "abbdabab";
string toFind = "ab";
string toSet = "X";
for (int index = source.IndexOf(toFind);
index >= 0;
index = source.IndexOf(toFind, index + 1)) {
string result = source.Substring(0, index) +
toSet +
source.Substring(index + toFind.Length);
Console.WriteLine(result);
}
Outcome:
Xbdabab
abbdXab
abbdabX
You can use a StringBuilder:
string s = "abbdabab";
var matches = Regex.Matches(s, "ab");
StringBuilder sb = new StringBuilder(s);
var m = matches[0]; // 0 for first output, 1 for second output, and so on
sb.Remove(m.Index, m.Length);
sb.Insert(m.Index, "x");
var result = sb.ToString();
Console.WriteLine(result);
You may use a dynamically built regex to be used with regex.Replace directly:
var s = "abbdabab";
var idx = 1; // First = 1, Second = 2
var search = "ab";
var repl = "x";
var pat = new Regex($#"(?s)((?:{search}.*?){{{idx-1}}}.*?){search}"); // ((?:ab.*?){0}.*?)ab
Console.WriteLine(pat.Replace(s, $"${{1}}{repl}", 1));
See the C# demo
The pattern will look like ((?:ab.*?){0}.*?)ab and will match
(?s) - RegexOptions.Singleline to make . also match newlines
((?:ab.*?){0}.*?) - Group 1 (later, this value will be put back into the result with ${1} backreference)
(?:ab.*?){0} - 0 occurrences of ab followed with any 0+ chars as few as possible
.*? - any 0+ chars as few as possible
ab - the search string/pattern.
The last argument to pat.Replace is 1, so that only the first occurrence could be replaced.
If search is a literal text, you need to use var search = Regex.Escape("a+b");.
If the repl can have $, add repl = repl.Replace("$", "$$");.

How to remove a portion of string

I want to remove word Test and Leaf from the specified string beginning only,not from the other side,so string Test_AA_234_6874_Test should be AA_234_6874_Test,But when i use .Replace it will replace word Test from everywhere which i don't want.How to do it
This is the code what i have done it
string st = "Test_AA_234_6874_Test";
st = st.Replace("Test_","");
You could use a regex to do this. The third argument of the regex replace method specifics how many times you want to replace.
string st = "Test_AA_234_6874_Test";
var regex = new Regex("(Test|Leaf)_");
var value = regex.Replace(st, "", 1);
Or if the string to replace only occurs on the start just use ^ which asserts the position at start of the string.
string st = "Test_AA_234_6874_Test";
var regex = new Regex("^(Test|Leaf)_");
var value = regex.Replace(st, "");
If you know that you allways have to remove the first 5 letters you can also use Substring which is more performant.
string st = "Test_AA_234_6874_Test";
var value = st.Substring(5, st.Length - 5);
The simplest way to do this is by using a Regular Expression like so.
using System;
using System.Text.RegularExpressions;
using System.Text;
namespace RegExTest
{
class Program
{
static void Main(string[] args)
{
var input = "Test_AA_234_6874_Test";
var matchText = "Test";
var replacement = String.Empty;
var regex = new Regex("^" + matchText);
var output = regex.Replace(input, replacement);
Console.WriteLine("Converted String: {0}", output);
Console.ReadKey();
}
}
}
The ^ will match text at the beginning of the string.
Consider checking whether the string starts with "Start" and/or ends with "Trim" and decide the end and start positions you'd like to maintain. Then use Substring method to get only the portion you need.
public string Normalize(string input, string prefix, string suffix)
{
// Validation
int length = input.Length;
int startIndex = 0;
if(input.StartsWith(prefix))
{
startIndex = prefix.Length;
length -= prefix.Length;
}
if (input.EndsWith (suffix))
{
length -= suffix.Length;
}
return input.Substring(startIndex, length);
}
Hope this helps.
string wordToRemoveFromBeginning = "Test_";
int index = st.IndexOf(wordToRemoveFromBeginning);
string cleanPath = (index < 0) ? st : st.Remove(index,
wordToRemoveFromBeginning.Length);
Use a regular expression.
var str1 = "Test_AA_234_6874_Test";
var str2 = "Leaf_AA_234_6874_Test";
str1 = Regex.Replace(str1, "^Test", "");
str2 = Regex.Replace(str2, "^Leaf", "");
Regex.Replace parameters are your input string (str1), the pattern you want to match, and what to replace it with, in this case a blank space. The ^ character means look at the start of the string, so something like "MyTest_AAAA_234_6874_Test" would stil return "MyTest_AA_234_6874_Test".
I am gonna use some very simple code here
string str = "Test_AA_234_6874_Test";
string substring = str.Substring(0, 4);
if (substring == "Test" || substring == "Leaf")
{
str= str.Remove(0, 5);
}

Change in string some part, but without one part - where are numbers

For example I have such string:
ex250-r-ninja-08-10r_
how could I change it to such string?
ex250 r ninja 08-10r_
as you can see I change all - to space, but didn't change it where I have XX-XX part... how could I do such string replacement in c# ? (also string could be different length)
I do so for -
string correctString = errString.Replace("-", " ");
but how to left - where number pattern XX-XX ?
You can use regular expressions to only perform substitutions in certain cases. In this case, you want to perform a substitution if either side of the dash is a non-digit. That's not quite as simple as it might be, but you can use:
string ReplaceSomeHyphens(string input)
{
string result = Regex.Replace(input, #"(\D)-", "${1} ");
result = Regex.Replace(result, #"-(\D)", " ${1}");
return result;
}
It's possible that there's a more cunning way to do this in a single regular expression, but I suspect that it would be more complicated too :)
A very uncool approach using a StringBuilder. It'll replace all - with space if the two characters before and the two characters behind are not digits.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
bool replace = false;
char c = text[i];
if (c == '-')
{
if (i < 2 || i >= text.Length - 2) replace = true;
else
{
bool leftDigit = text.Substring(i - 2, 2).All(Char.IsDigit);
bool rightDigit = text.Substring(i + 1, 2).All(Char.IsDigit);
replace = !leftDigit || !rightDigit;
}
}
if (replace)
sb.Append(' ');
else
sb.Append(c);
}
Since you say you won't have hyphens at the start of your string then you need to capture every occurrence of - that is preceded by a group of characters which contains at least one letter and zero or many numbers. To achieve this, use positive lookbehind in your regex.
string strRegex = #"(?<=[a-z]+[0-9]*)-";
Regex myRegex = new Regex(strRegex, RegexOptions.IgnoreCase | RegexOptions.Multiline);
string strTargetString = #"ex250-r-ninja-08-10r_";
string strReplace = #" ";
return myRegex.Replace(strTargetString, strReplace);
Here are the results:

C# RegEx string extraction

I have a string:
"ImageDimension=655x0;ThumbnailDimension=0x0".
I have to extract first number ("655" string) coming in between "ImageDimension=" and first occurrence of "x" ;
and need extract second number ("0" string) coming after first "x" occurring after "ImageDimension=" string. Similar with third and fourth numbers.
Can this be done with regex ("ImageDimension=? x ?;ThumbnailDimension=? x ?") and how ? Instead of clumsy substrings and indexof ? Thank you!
My solution which is not nice :
String configuration = "ImageDimension=655x0;ThumbnailDimension=0x0";
String imageDim = configuration.Substring(0, configuration.IndexOf(";"));
int indexOfEq = imageDim.IndexOf("=");
int indexOfX = imageDim.IndexOf("x");
String width1 = imageDim.Substring(indexOfEq+1, indexOfX-indexOfEq-1);
String height1 = imageDim.Substring(imageDim.IndexOf("x") + 1);
String thumbDim = configuration.Substring(configuration.IndexOf(";") + 1);
indexOfEq = thumbDim.IndexOf("=");
indexOfX = thumbDim.IndexOf("x");
String width2 = imageDim.Substring(indexOfEq + 1, indexOfX - indexOfEq-1);
String height2 = imageDim.Substring(imageDim.IndexOf("x") + 1);
This will get each of the values into separate ints for you:
string text = "ImageDimension=655x0;ThumbnailDimension=0x0";
Regex pattern = new Regex(#"ImageDimension=(?<imageWidth>\d+)x(?<imageHeight>\d+);ThumbnailDimension=(?<thumbWidth>\d+)x(?<thumbHeight>\d+)");
Match match = pattern.Match(text);
int imageWidth = int.Parse(match.Groups["imageWidth"].Value);
int imageHeight = int.Parse(match.Groups["imageHeight"].Value);
int thumbWidth = int.Parse(match.Groups["thumbWidth"].Value);
int thumbHeight = int.Parse(match.Groups["thumbHeight"].Value);
var groups = Regex.Match(input,#"ImageDimension=(\d+)x(\d+);ThumbnailDimension=(\d+)x(\d+)").Groups;
var x1= groups[1].Value;
var y1= groups[2].Value;
var x2= groups[3].Value;
var y2= groups[4].Value;
var m = Regex.Match(str,#"(\d+).(\d+).*?(\d+).(\d+)");
m.Groups[1].Value; // 655 ....
(\d+)
Get the first set of one or more digits. and store it as the first captured group after the entire match
.
Match any character
(\d+)
Get the next set of one or more digits. and store it as the second captured group after the entire match
.*?
match and number of any characters in a non greedy fashion.
(\d+)
Get the next set of one or more digits. and store it as the third captured group after the entire match
(\d+)
Get the next set of one or more digits. and store it as the fourth captured group after the entire match
Since a lot of people already gave you what you wanted, I will contribute with something else. Regexes are hard to read and error prone. Maybe a little less verbose than your implementation but more straightforward and friendly than using regex:
private static Dictionary<string, string> _extractDictionary(string str)
{
var query = from name_value in str.Split(';') // Split by ;
let arr = name_value.Split('=') // ... then by =
select new {Name = arr[0], Value = arr[1]};
return query.ToDictionary(x => x.Name, y => y.Value);
}
public static void Main()
{
var str = "ImageDimension=655x0;ThumbnailDimension=0x0";
var dic = _extractDictionary(str);
foreach (var key_value in dic)
{
var key = key_value.Key;
var value = key_value.Value;
Console.WriteLine("Value of {0} is {1}.", key, value.Substring(0, value.IndexOf("x")));
}
}
Sure, it's pretty easy. The regex pattern you're looking for is:
^ImageDimension=(\d+)x0;.+$
The first group in the match is the number you want.

C# String replacement using Regex

I currently have the code below, to replace a characters in a string but I now need to replace characters within the first X (in this case 3) characters and leave the rest of the string. In my example below I have 51115 but I need to replace any 5 within the first 3 characters and I should end up with 61115.
My current code:
value = 51115;
oldString = 5;
newString = 6;
result = Regex.Replace(value.ToString(), oldString, newString, RegexOptions.IgnoreCase);
result is now 61116. What would you suggest I do to query just the first x characters?
Thanks
Not particularly fancy, but only give regex the data it should be replacing; only send in the range of characters that should potentially be replaced.
result = Regex.Replace(value.ToString().Substring(0, x), oldString, newString, RegexOptions.IgnoreCase);
If you're just replacing a single character only, you could just write the code to do the replacement yourself. It'd be faster than messing with a substring and then a RegEx replace (which is a waste anyway if you're doing a single-char replacement).
StringBuilder sb = new StringBuilder(oldString.Length);
foreach(char c in oldString) {
if(c == replaceFrom) { c = replaceTo; }
sb.Append(c);
}
return sb.ToString();
I think the character-by-character option mentioned here is probably clearer, but if you really want a regex:
string result = "";
int value = 55555;
string oldString = "5";
string newString = "6";
var match = new Regex(#"(\d{1,3})(\d+)?").Match(value.ToString());
if (match.Groups.Count > 1)
result = match.Groups[1].Value.Replace(oldString, newString) + (match.Groups.Count > 2 ? match.Groups[2].Value : "");
I love RegEx, but in this case I would just do a .Replace
string value;
string oldString;
string newString;
value = "51115";
int iLenToLook;
iLenToLook = 3;
oldString = "5";
newString = "6";
string result;
result = value.Length > iLenToLook ? value.Substring(iLenToLook, value.Length - iLenToLook) :"";
result = value.Substring(0, value.Length >= iLenToLook ? iLenToLook : value.Length).Replace(oldString, newString) + result;
EDIT I changed it to get the non-replaced portion first, in case there were replacement strings of differing lengths than the original.
Every time someone in the .NET world has a question about regex, I recommend Expresso (link). It's a great tool for working in the confusing and thorny world of regular expressions.

Categories

Resources