I have defined enum events:
public enum Events {
UNLOCK = 1,
LOCK = 2
}
as well as CSV string:
var csv = "1,2";
What would be preferable way to convert csv string to List< Events> in C#?
csv.Split(',').Select(s => (Events)Enum.Parse(typeof(Events), s));
BTW with generic enum class you can parse this way Enum<Events>.Parse(s) and whole code will look like:
csv.Split(',').Select(Enum<Events>.Parse)
csv.Split(',').Select(x => (Events)int.Parse(x)).ToList();
A more verbose way:
var csv = "2,1,1,2,2,1";
List<Events> EventList = new List<Events>();
foreach (string s in csv.Split(','))
{
EventList.Add((Events)Enum.Parse( typeof(Events), s, true));
}
If your whole CSV line is not just events, use regex to parse out the line into its components. Here we have a mixed CSV line and regex can break out each of the values using named match captures. From there we parse it using linq into a new projection for each line of data found.
var csvLine = "1245,1,2,StackOverFlow";
var pattern = #"
^ # Start at the beginning of each line.
(?<IDasInteger>[^,]+) # First one is an ID
(?:,) # Match but don't capture the comma
((?<Events>[^,]+)(?:,)){2} # 2 Events
(?<Summary>[^\r\n]+) # Summary text";
var resultParsed = Regex.Matches(csvLine, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline)
.OfType<Match>()
.Select (mt => new {
ID = int.Parse (mt.Groups["IDasInteger"].ToString()),
Event = mt.Groups["Events"].Captures
.OfType<Capture>()
.Select (cp => (Events)Enum.Parse(typeof(Events), cp.Value))),
Summary = mt.Groups["Summary"].ToString()
});
Related
I have a collection of strings such as Some song [FEAT. John Doe] and I'm trying to extract the 'featured' part. It could be identified by one of several different words "FEAT|FEAT\\.|Featuring" and may or may not be enclosed by brackets. I'm using a Regex for this and here is what I've got so far:
[TestMethod]
public void ExtractFeaturedPerformers()
{
IEnumerable<string> titles = new string[]
{
"abc [FEAT one two] 123",
"def(FEAT. three'four) 456",
"ghi Featuring five",
"jkl"
};
// Must be able to use an arbitrary array of words
var arrayOfWords = new string[] { "FEAT", "FEAT.", "Featuring" };
string options = string.Join("|", arrayOfWords.Select(s => Regex.Escape(s)));
var result = new List<string>();
foreach(string title in titles)
{
var _ = Regex.Match(title, $#"(?<=({options})\s*)(.*?)(?=[\]\)]|$)");
if (_.Success)
result.Add(_.Value);
}
Assert.AreEqual(3, result.Count());
Assert.IsTrue(result.Contains("one two"));
Assert.IsTrue(result.Contains("three'four"));
Assert.IsTrue(result.Contains("five"));
}
I have it mostly working but there are two limitations. My main problem is that the second result includes the ..
. three'four
How can I remove this as part of the Regex so that I can accept an arbitrary options string rather than stripping it away later? Dealing with the . is my main concern but I would also appreciate suggestions for removing the leading and trailing whitespace from the result so that I don't have to call Trim() later.
You need
(?:FEAT\.?|Featuring)\s*([^])]*)
See the regex demo
Details
(?:FEAT\.?|Featuring) - FEAT and an optional . or Featuring
\s* - zero or more whitespace
([^])]*) - Capturing group 1: zero or more chars other than ] and ).
You need to amend the C# code to get Group 1 values.
Here is the full C# demo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
IEnumerable<string> titles = new string[]
{
"abc [FEAT one two] 123",
"def(FEAT. three'four) 456",
"ghi Featuring five",
"jkl"
};
var keys = new List<string> { "FEAT", "FEAT.", "Featuring" };
keys = keys.OrderByDescending(x => x.Length).ToList();
var pattern = $#"(?:{string.Join("|", keys.Select(z => Regex.Escape(z)))})\s*([^])]*)";
Console.WriteLine(pattern);
var result = new List<string>();
foreach(string title in titles)
{
var _ = Regex.Match(title, pattern);
if (_.Success)
result.Add(_.Groups[1].Value);
}
Console.WriteLine( result.Count()); // Assert.AreEqual(3, result.Count());
Console.WriteLine( result.Contains("one two") ); //Assert.IsTrue(result.Contains("one two"));
Console.WriteLine( result.Contains("three'four") ); //Assert.IsTrue(result.Contains("three'four"));
Console.WriteLine( result.Contains("five") ); // Assert.IsTrue(result.Contains("five"));
}
}
The output is
(?:Featuring|FEAT.|FEAT)\s*([^])]*)
3
True
True
True
Note how the regex pattern is built:
var keys = new List<string> { "FEAT", "FEAT.", "Featuring" }; initializes the keys string list with the search phrases
keys = keys.OrderByDescending(x => x.Length).ToList(); - sorts the items in the list by length in the descending order
var pattern = $#"(?:{string.Join("|", keys.Select(z => Regex.Escape(z)))})\s*([^])]*)"; - creates the regex pattern by putting the escaped search phrases into a non-capturing group with | alternation operator in between, (?:Featuring|FEAT\.|FEAT).
I have a long string I need to take out only substrings that are between { and }, and turn it into a Json object
This string
sys=t85,fggh{"Name":"5038.zip","Folder":"Root",,"Download":"services/DownloadFile.ashx?"} dsdfg x=565,dfg
{"Name":"5038.zip","Folder":"Root",,"Download":"services/DownloadFile.ashx?"}dfsdfg567
{"Name":"5038.zip","Folder":"Root",,"Download":"services/DownloadFile.ashx?"}sdfs
I have trash inside so I need to extract the substring of the data between { and }
My code is here, but I'm stuck, I can't remove the data that I already taken.
List<JsonTypeFile> AllFiles = new List<JsonTypeFile>();
int lenght = -1;
while (temp.Length>3)
{
lenght = temp.IndexOf("}") - temp.IndexOf("{");
temp=temp.Substring(temp.IndexOf("{"), lenght+1);
temp.Remove(temp.IndexOf("{"), lenght + 1);
var result = JsonConvert.DeserializeObject<SnSafe.JsonTypeFile>(temp);
AllFiles.Add(result);
}
Or using regex you can get the strings like this:
var regex = new Regex("{([^}]*)}");
var matches = regex.Matches(str);
var list = (from object m in matches select m.ToString().Replace("{",string.Empty).Replace("}",string.Empty)).ToList();
var jsonList = JsonConvert.SerializeObject(list);
The str variable containing your string as you provided in your question.
You can use a regex for this but what I would do is use .split ('{') to split into sections, skip the first section, and then using .split('}) to find the first portion of each section.
You can do this using LINQ
var data = temp
.Split('{')
.Skip(1)
.Select(v => v.Split('}').FirstOrDefault());
If I understand correctly, you just want to extract anything in-between the braces and ignore anything else.
The following regular expression should allow you to extract that info:
{[^}]*} (a brace, followed by anything that isn't a brace, followed by a brace)
You can extract all instances and then deserialize them using something along the lines of:
using System.Text.RegularExpressions;
...
List<JsonTypeFile> AllFiles = new List<JsonTypeFile>();
foreach(Match match in Regex.Matches(temp, "{[^}]*}"))
{
var result = JsonConvert.DeserializeObject<SnSafe.JsonTypeFile>(match.Value);
AllFiles.Add(result);
}
I need to remove certain strings after another string within a piece of text.
I have a text file with some URLs and after the URL there is the RESULT of an operation. I need to remove the RESULT of the operation and leave only the URL.
Example of text:
http://website1.com/something Result: OK(registering only mode is on)
http://website2.com/something Result: Problems registered 100% (SOMETHING ELSE) Other Strings;
http://website3.com/something Result: error: "Âíèìàíèå, îáíàðóæåíà îøèáêà - Ìåñòî æèòåëüñòâà ñîäåðæèò íåäîïóñòèìûå ê
I need to remove all strings starting from Result: so the remaining strings have to be:
http://website1.com/something
http://website2.com/something
http://website3.com/something
Without Result: ........
The results are generated randomly so I don't know exactly what there is after RESULT:
One option is to use regular expressions as per some other answers. Another is just IndexOf followed by Substring:
int resultIndex = text.IndexOf("Result:");
if (resultIndex != -1)
{
text = text.Substring(0, resultIndex);
}
Personally I tend to find that if I can get away with just a couple of very simple and easy to understand string operations, I find that easier to get right than using regex. Once you start going into real patterns (at least 3 of these, then one of those) then regexes become a lot more useful, of course.
string input = "Action2 Result: Problems registered 100% (SOMETHING ELSE) Other Strings; ";
string pattern = "^(Action[0-9]*) (.*)$";
string replacement = "$1";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
You use $1 to keep the match ActionXX.
Use Regex for this.
Example:
var r = new System.Text.RegularExpressions.Regex("Result:(.)*");
var result = r.Replace("Action Result:1231231", "");
Then you will have "Action" in the result.
You can try with this code - by using string.Replace
var pattern = "Result:";
var lineContainYourValue = "jdfhkjsdfhsdf Result:ljksdfljh"; //I want replace test
lineContainYourValue.Replace(pattern,"");
Something along the lines of this perhaps?
string line;
using ( var reader = new StreamReader ( File.Open ( #"C:\temp\test.txt", FileMode.Open ) ) )
using ( var sw = new StreamWriter(File.Open( #"C:\Temp\test.edited.txt", FileMode.CreateNew ) ))
while ( (line = reader.ReadLine()) != null )
if(!line.StartsWith("Result:")) sw.WriteLine(line);
You can use RegEx for this kind of processing.
using System.Text.RegularExpressions;
private string ParseString(string originalString)
{
string pattern = ".*(?=Result:.*)";
Match match = Regex.Match(originalString, pattern);
return match.Value;
}
A Linq approach:
IEnumerable<String> result = System.IO.File
.ReadLines(path)
.Where(l => l.StartsWith("Action") && l.Contains("Result"))
.Select(l => l.Substring(0, l.IndexOf("Result")));
Given your current example, where you want only the website, regex match the spaces.
var fileLine = "http://example.com/sub/ random text";
Regex regexPattern = new Regex("(.*?)\\s");
var websiteMatch = regexPattern.Match(fileLine).Groups[1].ToString();
Debug.Print("!" + websiteMatch + "!");
Repeating for each line in your text file. Regex explained: .* matches anything, ? makes the match ungreedy, (brackets) puts the match into a group, \\s matches whitespace.
I have a string and I want to split this string into an array as follows:
string stemp = "a,b,c,\"d,e f\",g,h";
array[0] = a
array[1] = b
array[2] = c
array[3] = d,e f
array[4] = g
array[5] = h
I have tried following syntax
string array[] = null;
array = stemp.split(',');
This looks like CSV - which is not so simple to parse (when taking escapes into consideration).
I suggest using a CSV parser, such as the TextFieldParser class that lives in the Microsoft.VisualBasic.FileIO namespace.
There are many alternatives, such as FileHelpers.
Using a CSV parser is probably the right solution but you can also use a regular expression:
var stemp = #"a,b,c,""d,e f"",g,h";
var regex = new Regex(#"^(?:""(?<item>[^""]*)""|(?<item>[^,]*))(?:,(?:""(?<item>[^""]*)""|(?<item>[^,]*)))*$");
var array = regex
.Match(stemp)
.Groups["item"]
.Captures
.Cast<Capture>()
.Select(c => c.Value)
.ToArray();
Unfortunately regular expressions tend to be incomprehensible so here are a short description of the individual parts:
""(?<item>[^""]*)""
This matches "d,e f".
(?<item>[^,]*)
This matches a and b etc. Both expressions capture the relevant part to the named group item.
These expressions (lets call them A and B) are combined using an alternation construct and grouped using a non-capturing group:
(?:A|B)
Lets call this new expression C. The entire expression is then (again using a non-capturing group):
^C(?:,C)*$
Here is the sample string like '/aaa/bbb/ccc/ddd' or '/aaa/zzz'
I want to get a Regex to get each block, like
aaa
bbb
ccc
ddd
thus, I wrote
Regex r = new Regex(#"(/[^/]*)*");
But it can only get last match,
/ddd
How can I get everyone, Many thanks.
update my question:
I know 'split',just for fun.
the situation is I have a string:
string s = #"ftp://127.0.0.1/TE ST.中文 空格CC/T # ES T.OK/# ##中文 测试##^##!aaa.txt";
I want to encode each block between /.../ (using Uri.EscapeDataString(each))
I prefer to use Regex.Replace, is it possible?
You don't need (and shouldn't use) regex for something so simple.
string s = "/aaa/bbb/ccc/ddd";
var blocks = s.Split('/');
foreach(var block in blocks) {
Console.WriteLine(block);
}
Output:
aaa
bbb
ccc
ddd
Edit: Oh, I see what you're trying to do. So now we don't want to remove empty entries and we want to say
string encoded = String.Join("/", blocks.Select(b => Uri.EscapeDataString(b)));
In this case, why not just split on / ?
String[] split = "/aaa/bbb/ccc/ddd".split("/");
(note, it has been a while since I wrote C#, so the above might contain one or two errors, however the idea should be clear.)
Your initial question, using a Regex:
Regex r = new Regex(#"(/[^/]*)");
var matches = r.Matches("/aaa/bbb/ccc/ddd");
foreach (var match in matches)
{
// ...
}
Simply removed the trailing * of your pattern.
Your second question:
Regex r = new Regex(#"/([^/]*)");
var result = r.Replace("1.1.1.1/aaa/bbb/ccc/test.ext", match => {
return string.Format("/{0}", Uri.EscapeDataString(match.Groups[1].Value));
});
thanks for everyone, i wrote them this morning.
string s = #"ftp://127.0.0.1/# #/中 文.NET/###_%TRY 字符.txt";
s = ftpUrlPattern.Replace(s, new MatchEvaluator((match) => {
return "/" + Uri.EscapeDataString(match.Groups["tag"].Value);
}));
the pattern like this:
static Regex ftpUrlPattern = new Regex(#"(?<!/)/(?<tag>[^/]+)");
You are probably calling the Match method and want Matches. However, you could also use the split method and just split on "/" (if i understand your use correctly).
To replace:
public void Replace(string input)
{
Regex r = new Regex(#"(/[^/]*)");
var matchEval = new MatchEvaluator(Encode);
r.Replace(input, matchEval);
}
public string Encode(Match m)
{
//TODO: Encode the match
}
Note: I have not run this but the methodology should be sound.