C# RegEx string extraction - c#

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.

Related

C# -Take a string between a text

I've got various string in a list:
Ord.cl. N. 2724 del 08/11/2019
and it can be also
Ord.cl. N. 2725/web del 08/11/2019
I have to take all the content that comes after 'N.' and before 'del'. As result I want
2724
2725/web
Can someone do code for that in C#? I know there is substring, but maybe there are better ways?
you can build some extention method like this
public string SubstringFromTo(this string input, int from, int to)
{
return input.Substring(from, (to - from));
}
public string SubstringFromTo(this string input, string from, string to)
{
var index1 = input.IndexOf(from) != -1 ? input.IndexOf(from) : 0;
var index2 = input.IndexOf(to) != -1 ? input.IndexOf(to) : (input.Length - 1);
return input.SubstringFromTo(index1, index2);
}
var asd = " ciao ** come stai ? asdasd".SubstringFromTo("**","?");
result = "come stai"
//.Trim() if you want
Using regular expressions, you might do:
var m = Regex.Match("Ord.cl. N. 2724 del 08/11/2019", #"(?<=N\.).*?(?=del)");
if (m.Success)
{
var result = m.Value;
}
Explanation of the regular expression:
(?<=N\.) looks for a preceding "N.".
.*? matches any sequence of characters, but as few as possible
(?=del) lools for a trailng "del".
If it's always that predictable (space before and after N. and space before and after del), then it's fairly simple. Use Substring and use IndexOf to find the occurrences of N. and del:
var theString = "Ord.cl. N. 2725/web del 08/11/2019";
var start = theString.IndexOf("N. ") + 3;
var length = theString.IndexOf(" del", start) - start;
var partIWant = theString.Substring(start, length).Trim();
Console.WriteLine(partIWant);
That also assumes that there will only ever be one occurrence of N. and del in your string.
for (int i = 0; i< list.Count-1; i++)
{
NDocList.Add(list[i].DocumentiOrigine.Split(new string[] { " N. " }, StringSplitOptions.None)[1]
.Split()[0]
.Trim());
}
solved with this somehow.

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 can I capitalize every third letter of a string in C#?

How can I capitalize every third letter of a string in C#?
I loop through the whole string with a for loop, but I can't think of the sequence right now.
I suspect you just want something like this:
// String is immutable; copy to a char[] so we can modify that in-place
char[] chars = input.ToCharArray();
for (int i = 0; i < chars.Length; i += 3)
{
chars[i] = char.ToUpper(chars[i]);
}
// Now construct a new String from the modified character array
string output = new string(chars);
That assumes you want to start capitalizing from the first letter, so "abcdefghij" would become "AbcDefGhiJ". If you want to start capitalizing elsewhere, just change the initial value of i.
var s = "Lorem ipsum";
var foo = new string(s
.Select((c, i) => (i + 1) % 3 == 0 ? Char.ToUpper(c) : c)
.ToArray());
You are already looping through the characters inside a string? Then add a counter, increment it on each iteration, and if it is 3, then use .ToUpper(currentCharacter) to make it upper case. Then reset your counter.
You could just use a regular expression.
If the answer is every third char then you want
var input = "sdkgjslgjsklvaswlet";
var regex = new Regex("(..)(.)");
var replacement = regex.Replace(input, delegate(Match m)
{
return m.Groups[1].Value + m.Groups[2].Value.ToUpper();
});
If you want every third character, but starting with the first you want:
var input = "sdkgjslgjsklvaswlet";
var regex = new Regex("(.)(..)");
var replacement = regex.Replace(input, delegate(Match m)
{
return m.Groups[1].Value.ToUpper() + m.Groups[2].Value;
});
If you want a loop, you can convert to a character array first, so you can alter the values.
For every third character:
var x = input.ToCharArray();
for (var i = 2; i <x.Length; i+=3) {
x[i] = char.ToUpper(x[i]);
}
var replacement = new string(x);
For every third character from the beginning:
var x = input.ToCharArray();
for (var i = 0; i <x.Length; i+=3) {
x[i] = char.ToUpper(x[i]);
}
var replacement = new string(x);

Getting parts of a string and combine them in C#?

I have a string like this: C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg
Now, what I want to do is to dynamically combine the last 4 numbers, in this case its 10000080 as result. My idea was ti split this and combine them in some way, is there an easier way? I cant rely on the array index, because the path can be longer or shorter as well.
Is there a nice way to do that?
Thanks :)
A compact way using string.Join and Regex.Split.
string text = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string newString = string.Join(null, Regex.Split(text, #"[^\d]")); //10000080
Use String.Split
String toSplit = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
String[] parts = toSplit.Split(new String[] { #"\" });
String result = String.Empty;
for (int i = 5, i > 1; i--)
{
result += parts[parts.Length - i];
}
// Gives the result 10000080
You can rely on array index if the last part always is the filename.
since the last part is always
array_name[array_name.length - 1]
the 4 parts before that can be found by
array_name[array_name.length - 2]
array_name[array_name.length - 3]
etc
If you always want to combine the last four numbers, split the string (use \ as the separator), start counting from the last part and take 4 numbers, or the 4 almost last parts.
If you want to take all the digits, just scan the string from start to finish and copy just the digits to a new string.
string input = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string[] parts = toSplit.Split(new char[] {'\\'});
IEnumerable<string> reversed = parts.Reverse();
IEnumerable<string> selected = reversed.Skip(1).Take(4).Reverse();
string result = string.Concat(selected);
The idea is to extract the parts, reverse them to keep only the last 4 (excluding the file name) and re reversing to rollback to the initial order, then concat.
Using LINQ:
string path = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
var parts = Path.GetDirectoryName(path).Split('\\');
string numbersPart = parts.Skip(parts.Count() - 4)
.Aggregate((acc, next) => acc + next);
Result: "10000080"
var r = new Regex(#"[^\d+]");
var match = r
.Split(#"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg")
.Aggregate((i, j) => i + j);
return match.ToString();
to find the number you can use regex:
(([0-9]{2})\\){4}
use concat all inner Group ([0-9]{2}) to get your searched number.
This will always find your searched number in any position in the given string.
Sample Code:
static class TestClass {
static void Main(string[] args) {
string[] tests = { #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg",
#"C:\Projects\test\whatever\files\media\10\00\00\80\some\foldertest.jpg",
#"C:\10\00\00\80\test.jpg",
#"C:\10\00\00\80\test.jpg"};
foreach (string test in tests) {
int number = ExtractNumber(test);
Console.WriteLine(number);
}
Console.ReadLine();
}
static int ExtractNumber(string path) {
Match match = Regex.Match(path, #"(([0-9]{2})\\){4}");
if (!match.Success) {
throw new Exception("The string does not contain the defined Number");
}
//get second group that is where the number is
Group #group = match.Groups[2];
//now concat all captures
StringBuilder builder = new StringBuilder();
foreach (var capture in #group.Captures) {
builder.Append(capture);
}
//pares it as string and off we go!
return int.Parse(builder.ToString());
}
}

Replace placeholders in order

I have a part of a URL like this:
/home/{value1}/something/{anotherValue}
Now i want to replace all between the brackets with values from a string-array.
I tried this RegEx pattern: \{[a-zA-Z_]\} but it doesn't work.
Later (in C#) I want to replace the first match with the first value of the array, second with the second.
Update: The /'s cant be used to separate. Only the placeholders {...} should be replaced.
Example: /home/before{value1}/and/{anotherValue}
String array: {"Tag", "1"}
Result: /home/beforeTag/and/1
I hoped it could works like this:
string input = #"/home/before{value1}/and/{anotherValue}";
string pattern = #"\{[a-zA-Z_]\}";
string[] values = {"Tag", "1"};
MatchCollection mc = Regex.Match(input, pattern);
for(int i, ...)
{
mc.Replace(values[i];
}
string result = mc.GetResult;
Edit:
Thank you Devendra D. Chavan and ipr101,
both solutions are greate!
You can try this code fragment,
// Begin with '{' followed by any number of word like characters and then end with '}'
var pattern = #"{\w*}";
var regex = new Regex(pattern);
var replacementArray = new [] {"abc", "cde", "def"};
var sourceString = #"/home/{value1}/something/{anotherValue}";
var matchCollection = regex.Matches(sourceString);
for (int i = 0; i < matchCollection.Count && i < replacementArray.Length; i++)
{
sourceString = sourceString.Replace(matchCollection[i].Value, replacementArray[i]);
}
[a-zA-Z_] describes a character class. For words, you'll have to add * at the end (any number of characters within a-zA-Z_.
Then, to have 'value1' captured, you'll need to add number support : [a-zA-Z0-9_]*, which can be summarized with: \w*
So try this one : {\w*}
But for replacing in C#, string.Split('/') might be easier as Fredrik proposed. Have a look at this too
You could use a delegate, something like this -
string[] strings = {"dog", "cat"};
int counter = -1;
string input = #"/home/{value1}/something/{anotherValue}";
Regex reg = new Regex(#"\{([a-zA-Z0-9]*)\}");
string result = reg.Replace(input, delegate(Match m) {
counter++;
return "{" + strings[counter] + "}";
});
My two cents:
// input string
string txt = "/home/{value1}/something/{anotherValue}";
// template replacements
string[] str_array = { "one", "two" };
// regex to match a template
Regex regex = new Regex("{[^}]*}");
// replace the first template occurrence for each element in array
foreach (string s in str_array)
{
txt = regex.Replace(txt, s, 1);
}
Console.Write(txt);

Categories

Resources