Replace specific instance of item in string with regex - c#

I am trying to build a parser that will replace a specific instance of a string. So for example I have a string that is sn+sn+sn*9, and I want to only replace the third instance of sn How can I do this with regex?
I have tried
var expression = "sn+sn+sn*9";
var regex = new Regex("sn");
expression = regex.Replace("sn",4.ToString());
//expression = regex.Replace("sn",4.ToString(),1,2);
Thanks in advance

int x = 0;
string repl = "ANYTHING";
string s = Regex.Replace("sn+sn+sn*9", "sn", m => (++x) == 3 ? repl : m.Value);
Explanation
The x variable is used to track the occurrence of sought text. As soon as Regex finds third occurrence, the MatchEvaluator delegate replaces this string with whatever is in repl variable. Otherwise, it just returns the same found string.

Here is one option, which uses the following regex pattern:
(?<=.*?\bsn\b.*?\bsn\b.*?)\bsn\b
This pattern literally says to replace sn, as a single term, when we have already seen two sn terms previously in the string. I use the replacement blah in the sample code below, though you may use any value you wish.
var term = #"sn";
var replacement = "blah";
var expression = term + "+" + term + "+" + term + "*9";
var pattern = #"(?<=.*?\b" + term + #"\b.*?\b" + term + #"\b.*?)\b" + term + #"\b";
var exp_trim = Regex.Replace(expression, #pattern, replacement);
Console.WriteLine(exp_trim);
sn+sn+blah*9
Demo

Here is another method using the index and length of the match
string expression = "sn+sn+sn*9";
Regex regex = new Regex("sn");
MatchCollection matches = regex.Matches(expression);
expression = expression.Substring(0, matches[2].Index) + "4".ToString() + expression.Substring(matches[2].Index + matches[2].Length);

Related

How to remove number from string after a specific character C#

I have a string that i need to remove the last number from the string.
For example
abc/wed/ash/123 or
abc/tues/1 or
abc/thurs/clou/nice/12
The string does not have a set amount of / in it, however I would like to separate the number after the last / from the string.
Therefore I would like to get
abc/wed/ash and 123
Everything I found needed a set amount of / in it for it to work.
If you need both halves you could try this:
var s = "abc/thurs/clou/nice/12";
var index = s.LastIndexOf('/');
var number = Int32.Parse(s.Substring(index + 1)); //12
var leftHalf = s.Substring(0, index); //abc/thurs/clou/nice
Get the last index of "/" on your input string, then use that result in Substring:
var input = "abc/wed/ash/123";
var lastIndex = input.LastIndexOf("/");
var part1 = input.Substring(0, lastIndex); // "abc/wed/ash"
var part2 = input.Substring(lastIndex + 1); // "123"
You can use regular expressions:
const string Input = "abc/def/123";
var regex = new Regex(#"(.+)/(\d+)$");
foreach (var group in regex.Match(Input).Groups)
Console.WriteLine(group.ToString());
Console.ReadKey();
UPDATE
OK, maybe I should do some explaining. By specifying a pattern, you can express quite cleanly what are the parts of your input that are of interest to you. In this case, for example, the pattern #(.+)/(\d+) tells the engine that you expect the input to contain any number of any characters, then a dash, then a number of digits. $ means that should be the end of the input.
When processing text input, consider regular expressions. :)
You can accomplish this in a variety of approaches, the cleanest approach is the answer by Francies. Which would be:
// Performant:
var input = "/Product/Electrical/Wire/4421";
var index = input.LastIndexOf('/');
var id = int.Parse(input.Substring(index + 1));
var url = input.Substring(0, index);
You could also do the following, which is a nice alternative syntax wise:
// Easy to read syntax.
var input = "/Product/Electrical/Wire/4421";
var id = input.Skip(input.LastIndexOf('/') + 1);
var url = input.Take(input.LastIndexOf('/'));
If you only need the number, you could do:
var input = "/Product/Electrical/Wire/4421";
var id = input.Split('/').Last();
Regex is your friend
Regex regex = new Regex(#"(.*?)(\d+)$");
Match match = regex.Match("abc/tues/1");
Console.WriteLine(match.Groups[1].Value); -->abc/tues/
Console.WriteLine(match.Groups[2].Value); -->1

Replacement evaluator contains number after replacement group

I want to dynamically adjust my replacement pattern and evaluator:
string pattern = "np";
string replacement = "ab";
string retval = Regex.Replace("Input", #"(.*)" + pattern + #"(.*)", #"$1" + replacement + #"$2";
// retval = "Iabut" => correct
string replacement = "12";
retval = Regex.Replace("Input", #"(.*)" + pattern + #"(.*)", #"$1" + replacement + #"$2";
// retval = "$112ut" => wrong
The problem is that in the second case my evaluator is "$112$2" so my first replacement group would be $112.
Is it possible to avoid such problems directly or do I need to put a delimiting character between my group definition and my string?
As a replacement argument, use
"${1}" + replacement.Replace("$", "$$") + "$2"
The braces in ${1} will make sure the first group is referred to and .Replace("$", "$$") will make it work well if the replacement has $ inside.

In C#, what is the recommended way to parse out a word inside certain characters?

In C#, I have a string coming in that I am reading into a variable that looks like this
var fullString = "Some random text (importantword)"
what is the easiest way to parse out the "importantword"? RegEx? doing just .IndexOf() for the "(" and ")" characters?
IndexOf is definitely the easiest.
https://msdn.microsoft.com/en-us/library/aa287734%28v=vs.71%29.aspx
Followed by a Substring.
var startIndex = fullString.IndexOf("(") + 1;
var endIndex = fullString.IndexOf(")");
var targetWord = fullString.Substring(startIndex, endIndex - startIndex);
EDIT: As pointed out in the comments below, I forgot startIndex was for the opening parenthesis instead of the actual word.
Regular expressions have two drawbacks: they may be slow compared to IndexOf() and they are usually not easy to read and understand. In your case, finding the text in parenthesis is easy and doesn't need regular expressions.
If your string always ends with ), then you can search for just the ( and remove the last character:
var start = fullString.IndexOf('(') + 1;
var end = fullString.Length - 1;
return fullString.Substring(start, end - start);
Otherwise, do both searches. In this last case, remember to use the IndexOf(char, int) overload to avoid searching for the entire string:
var start = fullString.IndexOf('(') + 1;
var end = fullString.IndexOf(')', start); // Notice the `start`
return fullString.Substring(start, end - start);
You could use capturing groups or lookarounds to get all the characters present between () brackets.
String input = #"Some random text (importantword)";
Regex rgx = new Regex(#"(?<=\()[^()]*(?=\))");
foreach (Match m in rgx.Matches(input))
Console.WriteLine(m.Groups[0].Value);
OR
String input = #"Some random text (importantword)";
Regex rgx = new Regex(#"\(([^()]*)\)");
foreach (Match m in rgx.Matches(input))
Console.WriteLine(m.Groups[1].Value);

C# regular expression (replace)

Assume I have the string:
10,11,12,13,14,ABC,DEF,GHI,66
I am looking to run a regex against it to only return 0-9 and the "," characters, essentially stripping anything else out.
I have looked at Regex.Replace, but something isn't quite right with it. My code below:
Regex reg = new Regex(#"[0-9,]+");
string input = reg.Replace(input, delegate(Match m)
{
return String.Empty;
});
How can I make this work?
Do you just want a ^ in that?
input = Regex.Replace(input, #"[^0-9,]+", "");
Would a match collection give you more control?
Using \d+[^,] you can get a collection of digits?
You could then loop through your collection and recreate your desired string.
using linq you could do the following:
var input = "10,11,12,13,14,ABC,DEF,GHI,66";
Regex re = new Regex(#"\d+[^,]");
input = (from Match m in re.Matches(input) select m.Value).Aggregate("", (acc, item) => acc + "," + item).TrimStart(',');
How about this:
var testString = "10,11,12,13,14,ABC,DEF,GHI,66";
var split = testString.Split(',');
var result = String.Join(",", split.Where(element => element.All(c => Char.IsDigit(c))).ToArray());
I think that you may do it without regular expressions via analysis of what is required for your characters in set [0123456789,].

Replacing text using regular expression with variable text?

Lets say I have some text with lots of instances of word "Find", which I want to replace it with text like "Replace1","Replace2","Replace3", etc. The number is the occurrence count of "Find" in the text.
How to do it in the most effective way in C#, I already know the loop way.
A MatchEvaluator can do this:
string input = "FindbcFinddefFind", pattern = "Find";
int i = 1;
string replaced = Regex.Replace(input, pattern, match => "REPLACE" + i++);
Note that the match variable also has access to the Match etc. With C# 2.0 you'll need to use an anonymous method rather than a lambda (but same effect) - to show both this and the Match:
string input = "FindbcFinddefFind", pattern = "Find";
int i = 1;
string replaced = Regex.Replace(input, pattern, delegate(Match match)
{
string s = match.Value.ToUpper() + i;
i++;
return s;
});
You could use the overload that takes a MatchEvaluator and provide the custom replacement string inside the delegate implementation, which would allow you to do all the replacements in one pass.
For example:
var str = "aabbccddeeffcccgghhcccciijjcccckkcc";
var regex = new Regex("cc");
var pos = 0;
var result = regex.Replace(str, m => { pos++; return "Replace" + pos; });

Categories