tags:

views:

176

answers:

5

How can we get the numbers 7 and 4 and 5 from the following string:

MODULE potmtpMAIN main <info: "Enterprise Optimizer 7.4 for COR Technology 5.5 --    
Advanced Solver Edition", url:"http://EO.riverlogic.com", url_menu:"EO Online...",  
app_id:"EOAS",app_name:"Enterprise Optimizer AS", app_major:7,  
app_minor:4,app_micro:5,app_copyright:"\251 1996-2010 River Logic Inc.\r\nAll 
Rights Reserved."> 

The search must be based on app_major: app_minor: and app_micro

Thank You in advance

+3  A: 

Just do a Regex, something like app_m....:\d might work, but I'm not sure (I usually use one of the tools like RegexBuilder to make them).

The documentation for Regex.Match has a sample to show you how to write the actual code to use the regex:

http://msdn.microsoft.com/en-us/library/twcw2f1c.aspx

Edit: Something like this might work:

Match m = Regex.Match(mystring, "app_major:\d{1-2}");
if(m.Success)
{
     string appMajor = m.Value.SubString(m.Value.IndexOf(":"));
}

If I remember correctly the \d{1-2} bit should mean that you want to get one or two digits.

ho1
So far I have this:If (Regex.IsMatch(mystring, "app_major")){ //sucess // I don't know what to do here to get the number that comes after "app_major"}else{ \\not found}
microsumol
@microsumol - I've updated my answer with a sample since the code looks better there than in the comment. I've not tested that code though.
ho1
+3  A: 

With regex (?<=:)\d(?=\*\*)

Edited : As the question is edited so is the answer. (?<=(app_major|app_minor|app_micro):)\d*

Draco Ater
Since OP edited question (presumably to get rid of a failed bold attempt) this regex should be `(?<=:)\d(?=,)`.
Daniel Rasmussen
+5  A: 

I did it using LINQ... might not be the best way but it was fun to figure it out:

string test = "<info:\"Enterprise Optimizer 7.4 for COR Technology 5.5 -- Advanced Solver Edition\", url:\"http://EO.riverlogic.com\", url_menu:\"EO Online...\", app_id:\"EOAS\",app_name:\"Enterprise Optimizer AS\", **app_major:7**, **app_minor:4**,**app_micro:5**,app_copyright:\"251 1996-2010 River Logic Inc.\r\nAll Rights Reserved.\">";

var result = test.Split(',').
    Select(p => p.Trim().Split(':')).
    Where(i => i[0].Trim().StartsWith("**app_")).
    Select(r => new { Key = r[0].Trim('*'), Value = r[1].TrimEnd('*') });

Produces:

result = {{Key = "app_major", Value = "7"},
          {Key = "app_minor", Value = "4"}, 
          {Key = "app_micro", Value = "5"}}

It could probably even be done much more elegantly :)

EDIT: If you want to make it very simple to access what you want do:

var result = test.Split(',').
    Select(p => p.Trim().Split(':')).
    Where(i => i[0].Trim().StartsWith("**app_")).
    Select(r => new { Key = r[0].Trim('*'), Value = r[1].TrimEnd('*') }).
    ToDictionary(k => k.Key, v => v.Value);

Then to get the value out just give it the key like this:

var version = result["app_major"] ?? "Not Found";

Note I have tested the LINQ solution vs the Regex solution and the LINQ version is not that much of a difference in terms of speed but it is a bit slower than the regex answers posted. The regex answer though do not clean the data for you and present it in a easy to use manner. The ToDictionary part really slows it down (in terms of real time though it is almost nothing still) but it does make the results easier to use.

Kelsey
If you're going to use LINQ, why not do `new []{"**app_major", "**app_minor", "**app_micro"}.Contains(i[0].Trim())` in your `Where` predicate? Not that I agree in any way that LINQ should be used as a replacement for regular expressions...
Michael Petito
@Michael Petito there is a ton of ways to do it I am sure and I am not saying LINQ is the right way to go either but just wanted to show that it could be done using LINQ.
Kelsey
+1 for something other than regular expressions. You know the saying... "now you've got 2 problems..." http://bit.ly/agDTvi
p.campbell
@Michael Petito changed it to be a bit more generic by just checking `StartsWith` in the `Where`. Little bit cleaner now :)
Kelsey
+2  A: 

Use a regular expression:

string regex = @"app_major:(?<major>\d+).*app_minor:(?<minor>\d+).*app_micro:(?<micro>\d+";
   RegexOptions options =        
      (RegexOptions.IgnorePatternWhitespace | 
      RegexOptions.Singleline | 
      RegexOptions.Multiline  | 
      RegexOptions.IgnoreCase);

Regex reg = new Regex(regex, options);

Match match = reg.Matches(yourString);

string major = match.Groups[1].Value
string minor = match.Groups[2].Value
string micro = match.Groups[3].Value
mjmarsh
I have this `using` directive you can borrow.
Jay Bazuzi
haha, sorry that was the autogenerated code given to me by Regulator. I've edited the namespace references out :)
mjmarsh
+1  A: 

Here is a simple regex to pick out each part, with example code for someone unfamiliar with regular expressions in .NET: (Edited, since the original question was edited to remove the asterisks).

Regex Exp = new Regex(@"(?<=\W)app_major:(?'Number'\d+)");

Match M = Exp.Match(input);

if(M.Success)
{
    string Number = M.Groups["Number"].Value;
}

You could just use 3 different expressions, one for each part you want to pick out of the string.

Explanation:

  • The first part (?<=\W) ensures that the match is preceded by a non-word character (in thise case, most likely a comma).
  • The second part app_major: matches the literal part of the string you're looking for.
  • (?'Number'\d+) is a captured group, which we label Number, where we're trying to match one or more digits \d+.
Michael Petito