c# regex groups - c#

How convert string to groups
STRING:
TableStart:Name="valueName";ClassName="valueClassName";MasterDatasource="valueMasterDatasource";Condition="valueCondition";ConditionParams="valueConditionParams";OrderBy="valueOrderBy"
OUTPUT GROUPS:
Name = "valueName"
ClassName = "valueClassName"
MasterDatasource = "valueMasterDatasource"
Condition = "valueCondition"
ConditionParams = "valueConditionParams"
OrderBy = "valueOrderBy"
Regex?
TableStart:Name=(?<Name>".*");ClassName=(?<ClassName>".*");MasterDatasource=(?<MasterDatasource>".*");Condition=(?<Condition>".*");ConditionParams=(?<ConditionParams>".*");OrderBy=(?<OrderBy>".*")

Try to use this snippet:
var s = "TableStart:Name=\"valueName\";ClassName=\"valueClassName\";MasterDatasource=\"valueMas" +
"terDatasource\";Condition=\"valueCondition\";ConditionParams=\"valueConditionParams\"" +
";OrderBy=\"valueOrderBy\"";
var reg = new Regex("TableStart:Name=(?<Name>\".*\");ClassName=(?<ClassName>\".*\");MasterDatasource=(?<Ma" +
"sterDatasource>\".*\");Condition=(?<Condition>\".*\");ConditionParams=(?<ConditionPa" +
"rams>\".*\");OrderBy=(?<OrderBy>\".*\")");
Match match = reg.Match(s);
GroupCollection groups = match.Groups;
for (int i = 1; i < groups.Count; i++)
{
Console.WriteLine("{0} = {1}", reg.GroupNameFromNumber(i), groups[i].Value);
}
prints:
Name = "valueName"
ClassName = "valueClassName"
MasterDatasource = "valueMasterDatasource"
Condition = "valueCondition"
ConditionParams = "valueConditionParams"
OrderBy = "valueOrderBy"
Edit: or you can use a much concise and shorter regexp
var reg = new Regex("\\w+\\=\"\\w+\"");
foreach (Match match in reg.Matches(s))
{
var values = match.Value.Split('=');
Console.WriteLine ("{0} = {1}",values[0], values[1]);
}
prints the same.

A regex-less alternative:
string input = "TableStart:Name=\"valueName\";ClassName=\"valueClassName\";MasterDatasource=\"valueMasterDatasource\";Condition=\"valueCondition\";ConditionParams=\"valueConditionParams\";OrderBy=\"valueOrderBy\"";
input = input.Replace("TableStart:", "");
string[] nameValues = input.Split(';');
foreach (string nameValue in nameValues){
string[] couple = nameValue.Split('=');
string name = couple[0];
string value = couple[1].Trim('"');
Console.WriteLine("{0} = {1}", name, value);
}

Related

How to get string between start and end character in C#

How to get substring of string like file_{AAA}_{BBB}.xml ?
My Code:
string[] result = Regex.Split(str, "{(.*)}"); result.ToList().ForEach(x => MessageBox.Show(x));
Result :
AAA
BBB
You can try this:
string str = "file_{AAA}_{BBB}.xml";
var regex = new Regex("(?<=\{)[^}]*(?=\})");
var matches = regex.Matches(str);
Super ghetto, I suck at regex and you should probably use Rahul's answer instead, but:
string f = "file_{AAA}_{BBB}.xml";
string o = String.Empty;
while (f.Contains('{') && f.Contains('}'))
{
int openIndex = f.IndexOf('{');
int closeIndex = f.IndexOf('}');
o += f.Substring(openIndex + 1, closeIndex - openIndex - 1) + " ";
f = f.Remove(0, closeIndex + 1);
}
o.Trim();
Console.WriteLine(o);
Will output AAA BBB
Original from Rahul Tripathi, just added removing of {}
string str = "file_{AAA}_{BBB}.xml";
var regex = new Regex("{.*?}");
var matches = regex.Matches(str);
List<string> result = new List<string>();
foreach (var item in matches)
{
result.Add(item.ToString().Replace("{", "").Replace("}", ""));
}
You may follow that:
string filename = string.Format(#"{0}", Path.GetFileName(fileUpload1.PostedFile.FileName));
string filepath = "f:\ClientDocument\" + Path.GetFileName(fileUpload1.PostedFile.FileName);
int fileLength = (fileUpload1.PostedFile.ContentLength) / 1024;

Easiest way to create a Regex with multiple scenario

I have function where I have 4 Regex scenario for search tire width..
string sizeWidthRgx = #"(\d{3})[\s\/]\d{2}[\s\/R]?[\s\/]\d{2}";
string sizeWidthRgxSecond = #"(\d{3})[\s\/ZR]?\s?\d{2}";
string sizeWidthRgxThird = #"(\d{2})\s?X?x?\s?\d{1,2}[,.]\d{2}";
string sizeWidthRgxFourth = #"(\d{3})[\s\/]\d{2}[\s\/]?R\d{2}";
var matchSizeWidth = Regex.Match(sizeWidthUpper, sizeWidthRgx);
var matchSizeWidthOther = Regex.Match(sizeWidthUpper, sizeWidthRgxSecond);
var matchSizeWidthThird = Regex.Match(sizeWidthUpper, sizeWidthRgxThird);
var matchSizeWidthFourth = Regex.Match(sizeWidthUpper, sizeWidthRgxFourth);
Someone have idea how i can join this all regex to one or other way to search this parametr.
For example:
(7.50)/80 R16, (305)/35 R24, (31)X10.50R15, (175)/65/14.
Thats all scenario i need to take all number from '()'
#Edit
Here is my code:
var sizeWidthUpper = productName.Trim().ToUpper();
string sizeWidthRgx = #"(\d{3})[\s\/]\d{2}[\s\/R]?[\s\/]\d{2}"; // 1 scenariusz
string sizeWidthRgxSecond = #"(\d{3})[\s\/ZR]?\s?\d{2}"; // 2 scenariusz
string sizeWidthRgxThird = #"(\d{2})\s?X?x?\s?\d{1,2}[,.]\d{2}"; //3 scenariusz, np. BARUM BRAVURIS 4X4 31X10.50R15 109 S FR
string sizeWidthRgxFourth = #"(\d{3})[\s\/]\d{2}[\s\/]?R\d{2}";
var matchSizeWidth = Regex.Match(sizeWidthUpper, sizeWidthRgx);
var matchSizeWidthOther = Regex.Match(sizeWidthUpper, sizeWidthRgxSecond);
var matchSizeWidthThird = Regex.Match(sizeWidthUpper, sizeWidthRgxThird);
var matchSizeWidthFourth = Regex.Match(sizeWidthUpper, sizeWidthRgxFourth);
int outSizeWidth = 0;
if(matchSizeWidth.Success)
{
if (int.TryParse(matchSizeWidth.Groups[1].Value, out outSizeWidth))
{
if ((outSizeWidth >= 125) && (outSizeWidth <= 335))
{
if ((outSizeWidth % 5) == 0) return outSizeWidth.ToString();
}
}
}
if (matchSizeWidthFourth.Success)
{
if (int.TryParse(matchSizeWidthFourth.Groups[1].Value, out outSizeWidth))
{
if ((outSizeWidth >= 125) && (outSizeWidth <= 335))
{
if ((outSizeWidth % 5) == 0) return outSizeWidth.ToString();
}
}
}
if(matchSizeWidthOther.Success)
{
if (int.TryParse(matchSizeWidthOther.Groups[1].Value, out outSizeWidth))
{
if ((outSizeWidth >= 125) && (outSizeWidth <= 335))
{
if ((outSizeWidth % 5) == 0) return outSizeWidth.ToString();
}
}
}
if(matchSizeWidthThird.Success)
{
if (int.TryParse(matchSizeWidthThird.Groups[1].Value, out outSizeWidth))
{
if ((outSizeWidth >= 30) && (outSizeWidth <= 37)) return outSizeWidth.ToString();
}
}
return string.Empty;
It works but I need to know can I shorten this code?
You can wrap each pattern in a named group ((?<name>...)), for instance:
string sizeWidthRgx = #"(?<width>(\d{3})[\s\/]\d{2}[\s\/R]?[\s\/]\d{2})";
Make sure that you assign a unique name to each sub-pattern. Then you can combine them all into one pattern separating them with or pipes:
IEnumerable<Match> matches = Regex.Matches(sizeWidthUpper, sizeWidthRgx + "|" + sizeWidthRgxSecond + "|" + sizeWidthRgxThird + "|" + sizeWidthRgxFourth);
Then you can loop through the matches and look to see if the named group exists in each of the matches (given that pattern, each match will only contain one group):
string matchSizeWidth = null;
string matchSizeWidthOther = null;
string matchSizeWidthThird = null;
string matchSizeWidthFourth = null;
foreach(Match m in matches)
{
Group g = m.Groups("width");
if(g.Success) matchSizeWidth = g.Value;
g = m.Groups("other");
if(g.Success) matchSizeWidthOther = g.Value;
g = m.Groups("third");
if(g.Success) matchSizeWidthThird = g.Value;
g = m.Groups("fourth");
if(g.Success) matchSizeWidthFourth = g.Value;
}
For your point:
Thats all scenario i need to take all number from '()'
You can just use this regex as well:
\((\d+(?:\.\d+)?)\)
Demo
To combine all regexes you can use | token which works as an OR condition:
regexpattern1|regexpattern2|regexpattern3
You could likely combine the patterns you've got into:
\(([0-9.]+)\)[X\/]([0-9.]+)[R\/\s]+([0-9]+)
This divides each numerical value into a group, which will then result in three groups.
Results:
7.50/80 R16
305/35 R24
31/10.50 R15
175/65 R14
Code:
string s = "(7.50)/80 R16, (305)/35 R24, (31)X10.50R15, (175)/65/14.";
string p = "\\(([0-9.]+)\\)[X\\/]([0-9.]+)[R\\/\\s]+([0-9]+)";
MatchCollection mc = Regex.Matches(s, p);
foreach (Match m in mc) {
Console.WriteLine("{0}/{1} R{2}", m.Groups[1], m.Groups[2], m.Groups[3]);
}
Example:
https://regex101.com/r/bF1rH0/1

String formatting in C#?

I have some problems to format strings from a List<string>
Here's a picture of the List values:
Now I managed to manipulate some of the values but others not, here's what I used to manipulate:
string prepareStr(string itemToPrepare) {
string first = string.Empty;
string second = string.Empty;
if (itemToPrepare.Contains("\"")) {
first = itemToPrepare.Replace("\"", "");
}
if (first.Contains("-")) {
int beginIndex = first.IndexOf("-");
second = first.Remove(beginIndex, first.Length - beginIndex);
}
return second;
}
Here's a picture of the Result:
I need to get the clear Path without the (-startup , -minimzed , MSRun , double apostrophes).
What am I doing wrong here?
EDIT my updated code:
void getStartUpEntries() {
var startEntries = StartUp.getStartUp();
if (startEntries != null && startEntries.Count != 0) {
for (int i = 0; i < startEntries.Count; i++) {
var splitEntry = startEntries[i].Split(new string[] { "||" }, StringSplitOptions.None);
var str = splitEntry[1];
var match = Regex.Match(str, #"\|\|""(?<path>(?:\""|[^""])*)""");
var finishedPath = match.Groups["path"].ToString();
if (!string.IsNullOrEmpty(finishedPath)) {
if (File.Exists(finishedPath) || Directory.Exists(finishedPath)) {
var _startUpObj = new StartUp(splitEntry[0], finishedPath,
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(finishedPath));
_startUpList.Add(_startUpObj);
}
else {
var _startUpObjNo = new StartUp(splitEntry[0], finishedPath,
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(string.Empty));
_startUpList.Add(_startUpObjNo);
}
}
var _startUpObjLast = new StartUp(splitEntry[0], splitEntry[1],
"Aktiviert: ", new Uri("/Images/inWatch.avOK.png", UriKind.RelativeOrAbsolute),
StartUp.getIcon(string.Empty));
_startUpList.Add(_startUpObjLast);
}
lstStartUp.ItemsSource = _startUpList.OrderBy(item => item.Name).ToList();
}
You could use a regex to extract the path:
var str = #"0Raptr||""C:\Program Files (x86)\Raptr\raptrstub.exe"" --startup"
var match = Regex.Match(str, #"\|\|""(?<path>(?:\""|[^""])*)""");
Console.WriteLine(match.Groups["path"]);
This will match any (even empty) text (either an escaped quote, or any character which is not a quote) between two quote characters preceeded by two pipe characters.
Similarly, you could simply split on the double quotes as I see that's a repeating occurrence in your examples and take the second item in the split array:
var path = new Regex("\"").Split(s)[1];
This is and update to your logic without using any Regex:
private string prepareStr(string itemToPrepare)
{
string result = null;
string startString = #"\""";
string endString = #"\""";
int startPoint = itemToPrepare.IndexOf(startString);
if (startPoint >= 0)
{
startPoint = startPoint + startString.Length;
int EndPoint = itemToPrepare.IndexOf(endString, startPoint);
if (EndPoint >= 0)
{
result = itemToPrepare.Substring(startPoint, EndPoint - startPoint);
}
}
return result;
}

Extract the word between the quotes and store the values in an variable

I need to extract the word between the quotes and store the values in an variable.
my actural string will be
m:'liquid' n:'4'
from the above string. I need to extract
the word liquid & 4
and to store like this
var m = "liquid";
var n = "4";
How can I do this in regular expression in c#
Well if the format is always that, then you can split by : and know that you will have an array of strings that start with the element you want, between ' chars.
Here is a generic solution
public Dictionary<string, string> GetValues(string input)
{
var results = new Dictionary<string, string>();
var pairs = input.Split(" ");
foreach(var pair in pairs)
{
var parts = pair.Split(":");
results.Add(parts[0], parts[1].Trim("'"));
}
return results;
}
var str = "m:'liquid' n:'4'";
var values = GetValues(str);
var m = values["m"];
var n = values["n"];
As you tagged your question with a "linq", you can try this:
var str = #"m:'liquid' n:'4'";
var r = str.Split(new [] {'\''}).Where((s, i) => i % 2 == 1).ToArray();
var m = r[0];
var n = r[1];
Regex regex = new Regex("(?<=')\\w+(?<!')");
var matches = regex.Matches("m:'liquid' n:'4'");
Will match any word preceeded by ' and followed by '.
var m = matches[0];
var n = matches[1];
var s = "m:'liquid' n:'4'";
var ss = s.Split(new char[]{' ', ':'}, StringSplitOptions.RemoveEmptyEntries);
You will have the pairs in ss: {"m", "'liquid'", "n", "'4'"}. It works if there is empty value ('').
You can actually use the .indexOf string
var x = "m:'liquid' n:'4'";
var split = x.Split(' ');
var indexm0 = split[0].IndexOf("'");
var indexm1 = split[0].LastIndexOf("'");
var m = split[0].Substring(indexm0, indexm1 - 1);
var indexn0 = split[1].IndexOf("'");
var indexn1 = split[1].LastIndexOf("'");
var n = split[1].Substring(indexn0, indexn1 - 1);

Getting rid of *consecutive* periods in a filename

I was wondering how I'd get rid of periods in a filename if i have a filename like:
Test....1.txt to look like Test 1.txt ? I do NOT want files like : 1.0.1 Test.txt to be touched. Only files with consecutive periods should be replaced with a space. Any ideas?
This is my current code but as you can see, it replaces every period aside from periods in extension names:
public void DoublepCleanUp(List<string> doublepFiles)
{
Regex regExPattern2 = new Regex(#"\s{2,}");
Regex regExPattern4 = new Regex(#"\.+");
Regex regExPattern3 = new Regex(#"\.(?=.*\.)");
string replace = " ";
List<string> doublep = new List<string>();
var filesCount = new Dictionary<string, int>();
try
{
foreach (string invalidFiles in doublepFiles)
{
string fileOnly = System.IO.Path.GetFileName(invalidFiles);
string pathOnly = System.IO.Path.GetDirectoryName(fileOnly);
if (!System.IO.File.Exists(fileOnly))
{
string filewithDoublePName = System.IO.Path.GetFileName(invalidFiles);
string doublepPath = System.IO.Path.GetDirectoryName(invalidFiles);
string name = System.IO.Path.GetFileNameWithoutExtension(invalidFiles);
//string newName = name.Replace(".", " ");
string newName = regExPattern4.Replace(name, replace);
string newName2 = regExPattern2.Replace(newName, replace);
string filesDir = System.IO.Path.GetDirectoryName(invalidFiles);
string fileExt = System.IO.Path.GetExtension(invalidFiles);
string fileWithExt = newName2 + fileExt;
string newPath = System.IO.Path.Combine(filesDir, fileWithExt);
System.IO.File.Move(invalidFiles, newPath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = doublepPath;
clean.Cells[1].Value = filewithDoublePName;
clean.Cells[2].Value = fileWithExt;
dataGridView1.Rows.Add(clean);
}
else
{
if (filesCount.ContainsKey(fileOnly))
{
filesCount[fileOnly]++;
}
else
{
filesCount.Add(fileOnly, 1);
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(fileOnly),
filesCount[fileOnly].ToString(),
System.IO.Path.GetExtension(fileOnly));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fileOnly), newFileName);
System.IO.File.Move(fileOnly, newFilePath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = fileOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
}
catch(Exception e)
{
//throw;
StreamWriter doublepcleanup = new StreamWriter(#"G:\DoublePeriodCleanup_Errors.txt");
doublepcleanup.Write("Double Period Error: " + e + "\r\n");
doublepcleanup.Close();
}
}
string name = "Text...1.txt";
Regex r = new Regex("[.][.]+");
string result = r.Replace(name, " ");
Well, to do that with a string:
string st = "asdf..asdf...asfd...asdf.asf.asdf.s.s";
Regex r = new Regex("\\.\\.+");
st = r.Replace(st, " ");
This will replace any instance of 2 or more '.'s with a space.
I would throw this into a method:
public static string StringReplace(string original,
string regexMatch, string replacement) {
Regex r = new Regex(regexMatch);
return r.Replace(original, replacement);
}
How about this?
string newFileName = String.Join(".", fileName.Split('.').Select(p => !String.IsNullOrEmpty(p) ? p : " ").ToArray())
Why not use something like this?
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", " ");
static string CleanUpPeriods(string filename)
{
StringBuilder sb = new StringBuilder();
if (filename.Length > 0) sb.Append(filename[0]);
for (int i = 1; i < filename.Length; i++)
{
char last = filename[i - 1];
char current = filename[i];
if (current != '.' || last != '.') sb.Append(current);
}
return sb.ToString();
}
You could use use regular expressions, something like this
string fileName = new Regex(#"[.][.]+").Replace(oldFileName, "");
Continuing from dark_charlie's solution, isn't
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", ".");
enough?
I have tested this code on a number of cases, and it appears to exhibit the requested behavior.
private static string RemoveExcessPeriods(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
// If there are no consecutive periods, then just get out of here.
if (!text.Contains(".."))
return text;
// To keep things simple, let's separate the file name from its extension.
string extension = Path.GetExtension(text);
string fileName = Path.GetFileNameWithoutExtension(text);
StringBuilder result = new StringBuilder(text.Length);
bool lastCharacterWasPeriod = false;
bool thisCharacterIsPeriod = fileName.Length > 0 && fileName[0] == '.';
bool nextCharacterIsPeriod;
for (int index = 0; index < fileName.Length; index++)
{
// Includes both the extension separator and other periods.
nextCharacterIsPeriod = fileName.Length == index + 1 || fileName[index + 1] == '.';
if (!thisCharacterIsPeriod)
result.Append(fileName[index]);
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod && !nextCharacterIsPeriod)
result.Append('.');
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod)
result.Append(' ');
lastCharacterWasPeriod = thisCharacterIsPeriod;
thisCharacterIsPeriod = nextCharacterIsPeriod;
}
return result.ToString() + extension;
}
I just made a change to handle some edge cases. Here are some test results for this version.
"Test....1.txt" => "Test 1.txt"
"1.0.1..Test.txt" => "1.0.1 Test.txt"
"Test......jpg" => "Test .jpg"
"Test.....jpg" => "Test .jpg"
"one.pic.jpg" => "one.pic.jpg"
"one..pic.jpg" => "one pic.jpg"
"one..two..three.pic.jpg" => "one two three.pic.jpg"
"one...two..three.pic.jpg" => "one two three.pic.jpg"
"one..two..three.pic..jpg" => "one two three.pic .jpg"
"one..two..three..pic.jpg" => "one two three pic.jpg"
"one..two..three...pic...jpg" => "one two three pic .jpg"
Combining some other answers...
static string CleanUpPeriods(string filename)
{
string extension = Path.GetExtension(filename);
string name = Path.GetFileNameWithoutExtension(filename);
Regex regex = new Regex(#"\.\.+");
string s = regex.Replace(name, " ").Trim();
if (s.EndsWith(".")) s = s.Substring(0, s.Length - 1);
return s + extension;
}
Sample Output
"Test........jpg" -> "Test.jpg"
"Test....1.jpg" -> "Test 1.jpg"
"Test 1.0.1.jpg" -> "Test 1.0.1.jpg"
"Test..jpg" -> "Test.jpg"
void ReplaceConsecutive(string src, int lenght, string replace)
{
char last;
int count = 0;
StringBuilder ret = new StringBuilder();
StringBuilder add = new StringBuilder();
foreach (char now in src)
{
if (now == last)
{
add.Append(now);
if (count > lenght)
{
ret.Append(replace);
add = new StringBuilder();
}
count++;
}
else
{
ret.Append(add);
add = new StringBuilder();
count = 0;
ret.Append(now);
}
}
return ret.ToString();
}
Untested, but this should work.
src is the string you want to check for consecutives, lenght is the number of equal chars followed by each other until they get replaced with replace.
This is AFAIK also possible in Regex, but I'm not that good with Regex's that I could do this.

Categories