Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working With Match and Regex

Tags:

c#

regex

I am working on a project that parses an incoming text file. I am learning C# as I go. My current method for picking out the information I need is something like:

string MyMatchString = @"a pattern to match";
Match MyMatch = Regex.Match(somestringinput, MyMatchString);
if (MyMatch.Succes)
{
   DoSomething(MyMatch.Value);
}

I am doing a lot of that. I'd like to be able to combine the match and the test for success in one step. Looking through the Class listings, Regex has an IsMatch() method, but it doesn't appear that I can access the matched value (assuming it is successful). I think I need a Match instance for that. I tried

if ((Match MyMatch = Regex.Match(somestringinput, MyMatchString).Success)

but of course got a compile error.

I am thinking a static method that takes the match pattern and the input then returns a bool is the way to go. Then I can just test for success, and if so grab the matched value.

like image 612
David Green Avatar asked Feb 13 '12 16:02

David Green


3 Answers

You can use foreach

string MyMatchString = @"a pattern to match";
foreach (Match match in Regex.Matches(somestringinput, MyMatchString))
{
    DoSomething(match.Value);
}

Optionally add break if you want only one match (or use .Take(1))

like image 176
sehe Avatar answered Oct 06 '22 03:10

sehe


Well you can write an extension method for Regex which would give you some power. The trick is doing it without running the regex match twice, which could be a problem for your performance (note: this hasn't been tested, and it differs from your idea in that it requires a ready-made Regex object to work).

public static class RegexExtensions {
    public static bool GetMatch(this Regex regex, string input, out string matched) {
        Match match = regex.Match(input);
        if (match.Success) {
            matched = match.Value;
            return true;
        }
        matched = null;
        return false;
    }
}

So you'd do something like

string matched;
Regex regex = new Regex(pattern);
if (regex.GetMatch(inputstring, matched))
{ /* do something with 'matched' */ }
else
{ /* no match, 'matched' is null */ }

You might prefer to just return null in the failure case and the string otherwise and dispense with the boolean and the output parameter.

like image 45
Matthew Walton Avatar answered Oct 06 '22 04:10

Matthew Walton


You could implement the "Try" convention used by TryParse and TryGetValue.

public static bool TryMatch(string input, string pattern, out Match match)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        match = m;
    }
    return m.Success;
}

// usage
string myMatchString = @"a pattern to match"; 
Match result = null;
if(TryMatch(somestringinput, myMatchString, out result))
{
    DoSomething(result.Value);
}

Alternatively, you can create higher-order functions that accept Action and Func delegates.

public void ActionOnMatch(string input, string pattern, Action<string> action)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        action(m.Value);
    }
}

public TResult FuncOnMatch<TResult>(string input, string pattern, 
    Func<string, TResult> func)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        return func(m.Value);
    }
    else
    {
        return default(TResult);
    }
}

/// usage
string pattern = @"a pattern to match"; 
ActionOnMatch(input, pattern, DoSomething);
var result = FuncOnMatch<string>(input, pattern, (val) => val);
like image 36
Corbin March Avatar answered Oct 06 '22 02:10

Corbin March